Code Block public func CC_SHA256(_ data: UnsafeRawPointer!, _ len: CC_LONG, _ md: UnsafeMutablePointer<UInt8>!) -> UnsafeMutablePointer<UInt8>!
comes as incorrect. For the same input data, different hash values are output containing lot of empty data. This only happens in release configuration.
The below code easily reproduces the issue when run in Release configuration. Release configuration is crucial here since it is not visible in Debug configuration. The issue is also visible when not run concurrently (in a single thread) but the frequency of occurrence is very less. The below code is not the usage but concurrent execution helps to create the issue easily
Code Block func sha256(data: Data) -> Data { var digestBytes = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) let buffer = CC_SHA256(Array(data), UInt32(data.count), &digestBytes)! return Data(bytes: buffer, count: Int(CC_SHA256_DIGEST_LENGTH)) } func testHashMismatch() { let rawInput = "Hello World!" // can be any input let input = Data(rawInput.utf8) let inputHash = self.sha256(data: input) print("inputHash: \(inputHash.base64EncodedString())") DispatchQueue.global(qos: .background).async { while (true) { let computedHash = self.sha256(data: input) if computedHash != inputHash { print("Value Mis-match !!! \(computedHash.base64EncodedString())") } } } DispatchQueue.global(qos: .background).async { while (true) { let computedHash = self.sha256(data: input) if computedHash != inputHash { print("Value Mis-match !!! \(computedHash.base64EncodedString())") } } } }
sample output:
Code Block inputHash: f4OxZX/x/FO5LcGBSKHWXfwtSx+j1ncoSt3SABJtkGk= Value Mis-match !!! f4OxZX/x/FO5LcGBAAAAAAAAAAAAAAAAAAAAAAAAAAA= Value Mis-match !!! f4OxZX8AAAAAAAAAAAAAAPwtSx+j1ncoSt3SABJtkGk= Value Mis-match !!! AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= Value Mis-match !!! AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
iOS: 13.x, 14.x
Swift: 5.3
The loop can be run for some value around 100,000 iterations but the mismatch occurrence varies and first occurrence is seen to vary from tens to hundreds to thousands, ten thousands of execution.
However, if the passed in value is used in the sha256(:) method defined above, the issue is not seen and behavior is as expected.
Code Block return Data(bytes: digestBytes, count: Int(CC_SHA256_DIGEST_LENGTH))
The only documentation for CC_SHA256 from Apple seems to be CC_SHA256 which states that return value should be same as the passed in pointer.
All routines return 1 except for the one-shot routines ( CC_SHA1(), etc.), which return the pointer passed in via the md parameter.
PS: This code has been working for a long time but started giving this issue few months back.
Would like to know if a bug needs to be reported and what is the recommendation for the usage?
The fix is really simple. Ignore the result from CC_SHA256 and change line 4 to this:
Code Block return Data(digestBytes)
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"