问题
I am migrating some codes from objective c to swift. I want to encrypt a string with a key using SHA 256 algorithm in swift. But comparing to Objective C implementation swift code returns different encrypted string. Both codes looks same only the syntax is different. Can someone help me get the same result in swift as I used to get in Objective C? Below are the code samples from both languages.
Objective C:
NSString* key = @"1234567890123456789012345678901234567890123456789012345678901234";
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [@"message" 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)];
NSString* encryptedString = hash.base64Encoding;
Swift:
let key = "1234567890123456789012345678901234567890123456789012345678901234"
let cKey = key.cString(using: .ascii)!
let cData = "message".cString(using: .ascii)!
var digest = [CUnsignedChar](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), cKey, cKey.count, cData, cData.count, &digest)
let hash = Data(digest)
let encryptedString = hash.base64EncodedString()
回答1:
The problem is that cKey and cData include the terminating null character of the strings, and in the Swift version that is counted in cKey.count and cData.count, whereas in the Objective-C version strlen(cKey) and strlen(cData) do not count the terminating null character of the strings.
Doing
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), cKey, strlen(key), cData, strlen("message", &digest)
instead would fix the issue in your example, but is not safe for non-ASCII characters.
What I actually would do is to convert the strings to Data values (which do not include a terminating null byte) with the UTF-8 representation. Then pass the underlying byte buffers to the encryption method:
let key = "1234567890123456789012345678901234567890123456789012345678901234"
let cKey = Data(key.utf8)
let cData = Data("message".utf8)
var digest = [CUnsignedChar](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
cKey.withUnsafeBytes { keyPtr in
cData.withUnsafeBytes { dataPtr in
CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA256), keyPtr.baseAddress, cKey.count, dataPtr.baseAddress, cData.count, &digest)
}
}
let hash = Data(digest)
let encryptedString = hash.base64EncodedString()
This produces the same result ZNjnsz2Uv5L0PvWIJjSh0BrOovuRXOSFWQ0s1Rd8VSM= as your Objective-C code.
来源:https://stackoverflow.com/questions/56288419/swift-sha256-encryption-returns-different-encrypted-string-compare-to-objective