2016-09-15 92 views
1

我試着用Arcane庫下面的數據來生成的iOS SHA256:生成SHA256 iOS中

字符串:Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS

重點:71DD0F73AFFBB47825FF9864DDE95F3B

結果是409dc622b3bef5c9fc46e45c3210111fcb4536d3a55833316fe0dc8154b3ea34

,我認爲是正確的。但是,Windows對方使用下面的代碼生成SHA256:

Windows Phone Source Code: 

public static string HmacSha256(string secretKey, string value) 
    { 
     var msg = CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8); 
     byte[] convertedHash = new byte[secretKey.Length/2]; 

     for (int i = 0; i < secretKey.Length/2; i++) 
     { 
      convertedHash[i] = (byte)Int32.Parse(secretKey.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); 
     } 

     // Create HMAC. 
     var objMacProv = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256); 
     CryptographicHash hash = objMacProv.CreateHash(convertedHash.AsBuffer()); 

     hash.Append(msg); 
     return CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()); 

    } 

,其結果是:94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73這是我得到了什麼不同。有人可以幫我解決這個問題,讓我知道上面的代碼在做什麼,以及如何在iOS中複製它。

編輯:

iOS Source code 

let key = self.md5(string: "71DD0F73AFFBB47825FF9864DDE95F3B") 

    let hash = HMAC.SHA256(str, key: key) 
+1

你沒有顯示有關的iOS側的任何代碼。另外SHA256和HMAC-SHA256是不同的東西。 –

+0

@SamiKuhmonen:我添加了iOS源代碼;它使用奧術圖書館。 –

回答

2

這裏的關鍵是你需要將你的祕密,這是一個十六進制字符串,轉換成NSData。換句話說,NSData字節流將「看起來」像祕密。

這應該做你想要什麼:

// Hex string to NSData conversion from here http://stackoverflow.com/questions/7317860/converting-hex-nsstring-to-nsdata 
    NSString *secret = @"71DD0F73AFFBB47825FF9864DDE95F3B"; 
    NSData *dataIn = [@"Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS" dataUsingEncoding:NSUTF8StringEncoding]; 
    NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; 

    secret = [secret stringByReplacingOccurrencesOfString:@" " withString:@""]; 
    NSMutableData *secretData = [[NSMutableData alloc] init]; 
    unsigned char whole_byte; 
    char byte_chars[3] = {'\0','\0','\0'}; 
    int i; 
    for (i=0; i < [secret length]/2; i++) { 
     byte_chars[0] = [secret characterAtIndex:i*2]; 
     byte_chars[1] = [secret characterAtIndex:i*2+1]; 
     whole_byte = strtol(byte_chars, NULL, 16); 
     [secretData appendBytes:&whole_byte length:1]; 
    } 

    CCHmac(kCCHmacAlgSHA256, secretData.bytes, secretData.length, dataIn.bytes, dataIn.length, macOut.mutableBytes); 

    NSMutableString *stringOut = [NSMutableString stringWithCapacity:macOut.length]; 
    const unsigned char *macOutBytes = macOut.bytes; 

    for (NSInteger i=0; i<macOut.length; ++i) { 
     [stringOut appendFormat:@"%02x", macOutBytes[i]]; 
    } 

    NSLog(@"dataIn: %@", dataIn); 
    NSLog(@"macOut: %@", macOut); 
    NSLog(@"stringOut: %@", stringOut); 

輸出:

2016年9月27日20:18:54.181 JKS [27562:5321334]數據輸入:< 416d6f75 6e743d35 30264269 6c6c6572 49443d35 39264368 616e6e65 6c49443d 3226436f 6e746578 743d3334 7c636865 636b7c74 65737426 52657475 726e5552 4c3d6874 7470733a 2f2f7561 742e6d79 6661746f 6f72612e 636f6d2f 52656365 69707450 73707826 4f432e61 54786e52 65664e75 6d3d3030 30303030 30303030 32303030 33265573 65724e61 6d653d44 4353>

2016年9月27日20:18:54.181 JKS [27562:5321334] macOut:< 94a20ca3 9c8487c7 763823ec 9c918d9e 38ae83cb 741439f6 d129bcde f9edba73>

2016年9月27日20時18分54秒。181個JKS [27562:5321334] stringOut:94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73

與斯威夫特更新(代碼應該被清理)

// http://stackoverflow.com/questions/29799361/generate-a-hmac-swift-sdk8-3-using-cchmac 
func generateHMAC(key: String, data: String) -> String { 
    let keyData = key.dataFromHexadecimalString()! as NSData 
    let dataIn = data.data(using: .utf8)! as NSData 
    var result: [CUnsignedChar] 
    result = Array(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) 
    CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyData.bytes, keyData.length, dataIn.bytes, dataIn.length, &result) 

    let hash = NSMutableString() 
    for val in result { 
     hash.appendFormat("%02hhx", val) 
    } 

    return hash as String 
} 

您可以使用此擴展到十六進制字符串轉換爲Data

// Modified slightly http://stackoverflow.com/questions/26501276/converting-hex-string-to-nsdata-in-swift 
extension String { 

    func dataFromHexadecimalString() -> Data? { 
     var data = Data(capacity: characters.count/2) 

     let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive) 
     regex.enumerateMatches(in: self, options: [], range: NSMakeRange(0, characters.count)) { match, flags, stop in 
      let byteString = (self as NSString).substring(with: match!.range) 
      var num = UInt8(byteString, radix: 16) 
      data.append(&num!, count: 1) 
     } 

     return data 
    } 
} 

並使用類似的東西:

let secret = "71DD0F73AFFBB47825FF9864DDE95F3B" 
    let value = "Amount=50&BillerID=59&ChannelID=2&Context=34|check|test&ReturnURL=https://uat.myfatoora.com/ReceiptPOC.aspx&TxnRefNum=000000000020003&UserName=DCS" 

    print("\(generateHMAC(key: secret, data: value))") 

輸出應該是94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73

您需要#import <CommonCrypto/CommonCrypto.h>在你的橋接報頭。

+0

哦,你需要#import

+0

呃,對不起,它是Obj-C,但你應該可以用Swift做同樣的事情,'CCHmac'可以在那裏使用。這是一個鏈接到一些參考做這個http://stackoverflow.com/questions/29799361/generate-a-hmac-swift-sdk8-3-using-cchmac –

+0

嗨,謝謝你的答案。你能否告訴我什麼是data data in dataIn = data.data(使用:.utf8)!作爲NSData'因爲它給我錯誤。我假設你將字符串轉換爲NSData。 –

1

的Windows代碼採取字符串,將其解釋爲十六進制數,和兩個字符的時間轉換成一個字節。

您的Mac代碼最喜歡的字符串是,因爲它是。由於密鑰以「71」開頭,因此您的Windows代碼將其作爲值爲0x71 = 129的單個字節,您的Mac代碼將其作爲值爲'7'= 55且'1'= 49的兩個字節。

所有你需要做的就是像在Windows上一樣轉換Mac上的字節。您可能不得不做不可想象的事情,並查看Mac庫的源代碼,以查看它如何進行實際的哈希計算。

+0

我試圖在0 ... secretKey.length/2 { 設範圍內這樣做 ',對於i = NSMakeRange(I * 2,2) 如果range.location <32 { convertedHash.appendData(祕密密鑰.substringWithRange(range).dataUsingEncoding(NSUTF8StringEncoding)!) } }' 但它沒有幫助。你可以請張貼一些代碼。 –

0

#import <CommonCrypto/CommonHMAC.h> 
 

 
+ (NSString *)hmacSHA256EncryptString{ 
 

 

 
    NSString * parameterSecret = @"input secret key"; 
 
    NSString *plainString = @"input encrypt content string"; 
 
    const char *secretKey = [parameterSecret cStringUsingEncoding:NSUTF8StringEncoding]; 
 
    const char *plainData = [plainString cStringUsingEncoding:NSUTF8StringEncoding]; 
 
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH]; 
 
    CCHmac(kCCHmacAlgSHA256, secretKey, strlen(secretKey), plainData, strlen(plainData), cHMAC); 
 
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)]; 
 
    const unsigned char *bufferChar = (const unsigned char *)[HMACData bytes]; 
 
    NSMutableString *hmacString = [NSMutableString stringWithCapacity:HMACData.length * 2]; 
 
    for (int i = 0; i < HMACData.length; ++i){ 
 
     [hmacString appendFormat:@"%02x", bufferChar[i]]; 
 
    } 
 
    return hmacString; 
 
    
 
}