【问题标题】:Generating SHA256 in iOS在 iOS 中生成 SHA256
【发布时间】:2017-01-23 00:38:06
【问题描述】:

我尝试使用 Arcane 库在 iOS 中生成 SHA256,其中包含以下数据:

字符串: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)

【问题讨论】:

  • 您没有显示任何有关 iOS 端的代码。 SHA256 和 HMAC-SHA256 也是不同的东西。
  • @SamiKuhmonen:我已经添加了 iOS 源;它正在使用奥术库。

标签: ios windows-phone sha256 hmac


【解决方案1】:

#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;
    
}

【讨论】:

    【解决方案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] DATAIN:

    2016-09-27 20:18:54.181 JKS[27562:5321334] macOut:

    2016-09-27 20:18:54.181 JKS[27562:5321334] stringOut: 94a20ca39c8487c7763823ec9c918d9e38ae83cb741439f6d129bcdef9edba73

    用 Swift 更新(代码应该被清理)

    // 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 &lt;CommonCrypto/CommonCrypto.h&gt;

    【讨论】:

    • 哦,你需要#import
    • 呃,对不起,它是 Obj-C,但你应该可以用 Swift 做同样的事情,CCHmac 在那里可用。这是一个链接到一些关于这样做的参考stackoverflow.com/questions/29799361/…
    • 您好,感谢您的回答。你能告诉我`let dataIn = data.data(使用:.utf8)中的data.data是什么!作为 NSData`,因为它给了我错误。我假设您正在将 String 转换为 NSData。
    • 非常感谢@MobileBen。这正是我所需要的。
    【解决方案3】:

    Windows 代码获取字符串,将其解释为十六进制数,并将两个字符一次转换为一个字节。

    您的 Mac 代码最喜欢使用字符串 。由于密钥以“71”开头,您的 Windows 代码将其作为一个字节,值为 0x71 = 129,您的 Mac 代码将其作为两个字节,值为 '7' = 55 和 '1' = 49。

    您需要做的就是在 Mac 上像在 Windows 上一样转换字节。您可能不得不做一些不可思议的事情并查看 Mac 库的源代码,以了解它是如何进行实际哈希计算的。

    【讨论】:

    • 我试图做这样的事情` for i in 0...secretKey.length / 2 { let range = NSMakeRange(i*2, 2) if range.location
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    相关资源
    最近更新 更多