2016-09-15 56 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; 
 
    
 
}