2014-07-18 48 views
0

我正在使用HMAC SHA256在我的Android應用程序中創建base64哈希。並將其發送到服務器以與服務器端哈希匹配。
正在關注this教程。使用C#腳本的Android base64哈希與服務器端哈希不匹配

工作Android的代碼:

public String getHash(String data,String key) 
{ 

    try 
    { 
     String secret = key; 
     String message = data; 

     Mac sha256_HMAC = Mac.getInstance("HmacMD5"); 
     SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacMD5"); 
     sha256_HMAC.init(secret_key); 

     String hash = Base64.encodeBase64String(sha256_HMAC.doFinal(message.getBytes())); 
     System.out.println(hash); 
     return hash; 
} 
catch (Exception e){ 
    System.out.println("Error"); 
} 

}

服務器代碼是在C#腳本及其按以下

using System.Security.Cryptography; 

namespace Test 
{ 
     public class MyHmac 
     { 
      private string CreateToken(string message, string secret) 
      { 
       secret = secret ?? ""; 
       var encoding = new System.Text.ASCIIEncoding(); 
       byte[] keyByte = encoding.GetBytes(secret); 
       byte[] messageBytes = encoding.GetBytes(message); 
       using (var hmacsha256 = new HMACSHA256(keyByte)) 
       { 
        byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); 
        return Convert.ToBase64String(hashmessage); 
       } 
      } 
     } 
} 

但散列鍵在機器人側沒有與服務器相匹配生成下面是客觀的C代碼,其生成與C#代碼相同的代碼

ob jective的C代碼:

#import "AppDelegate.h" 
    #import <CommonCrypto/CommonHMAC.h> 

    @implementation AppDelegate 

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
    { 
     NSString* key = @"secret"; 
     NSString* data = @"Message"; 

     const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding]; 
     const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding]; 
     unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; 
     CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC); 
     NSData *hash = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)]; 

     NSLog(@"%@", hash); 

     NSString* s = [AppDelegate base64forData:hash]; 
     NSLog(s); 
    } 

    + (NSString*)base64forData:(NSData*)theData 
    { 
     const uint8_t* input = (const uint8_t*)[theData bytes]; 
     NSInteger length = [theData length]; 

     static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/="; 

     NSMutableData* data = [NSMutableData dataWithLength:((length + 2)/3) * 4]; 
     uint8_t* output = (uint8_t*)data.mutableBytes; 

     NSInteger i; 
     for (i=0; i < length; i += 3) { 
      NSInteger value = 0; 
      NSInteger j; 
      for (j = i; j < (i + 3); j++) { 
       value <<= 8; 

       if (j < length) { value |= (0xFF & input[j]); 
      } 
     } 
       NSInteger theIndex = (i/3) * 4; output[theIndex + 0] = table[(value >> 18) & 0x3F]; 
       output[theIndex + 1] = table[(value >> 12) & 0x3F]; 
       output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; 
       output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; 
    } 

    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
} 

@end 

請大家幫我出SOVE這個問題, 在此先感謝。

我已經通過將HmacSHA256更改爲HmacMD5並且給出了與C#代碼相同的哈希值來解決此問題。

我已更新我的問題與工作代碼。檢查它

+0

請注意,自iOS 7和OSX 10.9以來,有一種方法可以對Base64進行編碼和解碼:'base64EncodedDataWithOptions:'和'base64EncodedStringWithOptions:'。 – zaph

+0

您獲得Android的價值,請參閱psudo答案中的Objective-C輸出。看起來這只是一個Android問題。 – zaph

+0

@Zaph in Objective-c得到輸出長度爲24,在android側爲42. – user1269656

回答

0

在android secret.getBytes可能會得到UTF-16字節,檢查結果的長度。通常將這些功能分成單獨的語句以便於調試。

不是答案,一個簡單的OBJ-C實現的,而示範,並提供哈希和Base64編碼vaules:

NSString* key = @"secret"; 
NSString* data = @"Message"; 

NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding]; 
NSData *dataData = [data dataUsingEncoding:NSASCIIStringEncoding]; 
NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; 
CCHmac(kCCHmacAlgSHA256, keyData.bytes, keyData.length , dataData.bytes, dataData.length, hash.mutableBytes); 

NSLog(@"hash: %@", hash); 

NSString* s = [hash base64EncodedStringWithOptions:0]; 
NSLog(@"s: %@", s); 

輸出:

hash: <aa747c50 2a898200 f9e4fa21 bac68136 f886a0e2 7aec70ba 06daf2e2 a5cb5597> 
s: qnR8UCqJggD55PohusaBNviGoOJ67HC6Btry4qXLVZc= 
0

我懷疑這是一個編碼問題。 在一個示例中,指定將字符串轉換爲字節數組時,應使用ASCII對字符串進行編碼。在另一個示例中,您不指定編碼。 如果默認編碼是ASCII以外的任何其他字符,則意味着字節數組將不同,導致不同的散列結果。

+0

可能不是編碼,例子有ASCII字符。但可能是Android'getBytes'返回UTF-16(unichar)字節。 – zaph

+0

@Zaph我該如何解決這個問題? – user1269656

+0

在兩個平臺上使用相同的編碼。例如;在.NET端使用UTF8Encoding而不是ASCIIEncoding,然後在Java端使用secred.getBytes(Charsets.UTF_8)。這將意味着雙方將使用相同的編碼,以便從文本中獲得相同的字節數組。 (或者使用UTF16或其他任何你喜歡的編碼,只要確保它們在兩個系統上都是相同的)。 –