简体   繁体   English

C# 中的 HMAC SHA256 与 Swift 中的 HMAC SHA256 不匹配

[英]HMAC SHA256 in C# vs HMAC SHA256 in Swift don't match

Using the 'standard' HMACSHA256 technique in dotnetcore C# I can produce a hashed string as follows:使用 dotnetcore C# 中的“标准”HMACSHA256 技术,我可以生成如下哈希字符串:

private static void Test()
{
    var hmac = new HMACSHA256(Encoding.UTF8.GetBytes("testingkey"));
    var theHash = hmac.ComputeHash(Encoding.UTF8.GetBytes("testingstringtohash"));
    string signature = Convert.ToBase64String(theHash);
    Console.WriteLine(signature);
}
//Produces yg/9NCAm5IIwGKJK80PyUeBWkzEUwZswvC3OVnTnT80=

To do the same in swift (solution from this answer seems to be the 'standard' that people are using)在 swift 中做同样的事情(这个答案的解决方案似乎是人们正在使用的“标准”)

func HashTest() {
    let hash = "testingstringtohash".hmac(algorithm: .SHA256, key: "testingkey")
    //hash ca0ffd342026e4823018a24af343f251e056933114c19b30bc2dce5674e74fcd
    let hexData = hash.data(using: String.Encoding.utf8)
    let signature = hexData?.base64EncodedString()
    print(signature!)
}
//Produces Y2EwZmZkMzQyMDI2ZTQ4MjMwMThhMjRhZjM0M2YyNTFlMDU2OTMzMTE0YzE5YjMwYmMyZGNlNTY3NGU3NGZjZA==

Am I being stupid here... or should these two values be the same, as it is the same encryption algorithm, and the same key for the same value.我在这里是不是很愚蠢......或者这两个值应该相同,因为它是相同的加密算法,并且相同值的相同密钥。 As far as I can tell the C# example produces the 'correct' result, as a webservice that is consuming a value produced with that example works fine, but the value that the swift version produces is failing.据我所知,C# 示例产生“正确”结果,因为使用该示例产生的值的 Web 服务工作正常,但 swift 版本产生的值失败。

The issue here seems to be a difference in the base64 strings between the given swift solution and then C# solution.这里的问题似乎是给定 swift 解决方案和 C# 解决方案之间的 base64 字符串存在差异。

The output of the hash algorithm was the same at a byte level but it was being manipulated through various string conversions before being returned. hash 算法的 output 在字节级别上是相同的,但在返回之前通过各种字符串转换对其进行操作。

The function function

private func stringFromResult(result: UnsafeMutablePointer<CUnsignedChar>, length: Int) -> String {
let hash = NSMutableString()
for i in 0..<length {
        hash.appendFormat("%02x", result[i])
    }
    return String(hash).lowercased()
}

Which is part of the solution converts the raw hashed data to a string, which is then converted back to a data object in the calling class, which is then cast into a base64 string to be returned.这是解决方案的一部分,将原始散列数据转换为字符串,然后在调用 class 时将其转换回数据 object,然后将其转换为 base64 字符串以返回As we are getting a base64 string of of the string that was returned and not the raw bytes, I think this is where the issue was.由于我们得到的是返回的字符串的 base64 字符串,而不是原始字节,我认为这就是问题所在。

By changing the hmac code from the solution to this, we can cast the raw output of the has to a base64 string and avoid the other steps.通过将 hmac 代码从解决方案更改为此,我们可以将 has 的原始 output 转换为 base64 字符串并避免其他步骤。 This matches the C# value.这与 C# 值匹配。

func hmac(algorithm: CryptoAlgorithm, key: String) -> String {
    let str = self.cString(using: String.Encoding.utf8)
    let strLen = Int(self.lengthOfBytes(using: String.Encoding.utf8))
    let digestLen = algorithm.digestLength
    let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
    let keyStr = key.cString(using: String.Encoding.utf8)
    let keyLen = Int(key.lengthOfBytes(using: String.Encoding.utf8))
        
    CCHmac(algorithm.HMACAlgorithm, keyStr!, keyLen, str!, strLen, result)
    let a = UnsafeMutableBufferPointer(start: result, count: digestLen)
    let b = Data(a)        
    result.deallocate()        
    let digest = b.base64EncodedString()        
    return digest
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM