I have done some further research on the matter and it appears that the data you have inside the UIImage
is indeed different from the data that you open as a file, and I believe that is exactly what causes the problem. Note that I have shortened the base64 data, for readability.
Swift
func getImageHash(data: Data) -> String {
var hashBytes = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)
data.withUnsafeBytes {
_ = CC_SHA256($0.baseaddress, CC_LONG(data.count), &hashBytes)
}
var hex = ""
for index in 0 ..< Int(CC_SHA256_DIGEST_LENGTH) {
hex += String(format: "%02x", hashbytes[index])
}
return hex
}
The function is fine, I'll use an example using the assets folder of iOS.
let imageData = UIImage(named: "Example")!.pngData()!
print(imageData.base64EncodedString())
// 'iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg=='
let imageHash = getImageHash(data: imageData)
print(imageHash)
// '145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397'
The hash is calculated correctly as far as we are concerned right now. I was interested in the base64 data, so I can use that on other platforms too.
Python
import hashlib
import base64
img_d = base64.b64decode('iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg==')
m = hashlib.sha256()
m.update(img_d)
m.digest().hex()
# '145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397'
So it appears the hash is calculated correctly, but only for the base64 data. So what is the difference? Let's use Python again to investigate. I used PIL to load the image directly.
import hashlib
from PIL import Image
i = Image.open('/path/to/file')
img_d = i.tobytes()
m = hashlib.sha256()
m.update(img_d)
m.digest().hex()
# 'f650b1b95a50c3a2b77da7a0825c3c01066385a12c8fe50b449ffc8c7249e370'
So now we have, indeed, a different hash. Let's try one last thing, openssl dgst
in the terminal.
Terminal
echo 'iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg==' | base64 --decode | openssl dgst -sha256
145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397
Alright, so indeed, openssl digest can calculate the hash over the base64 data and it does indeed match.
openssl dgst -sha256 /path/to/file
SHA256(/path/to/file)= d15c2d0c186a46b41c34a312eaf1c7e4b0f7a51bdb9c53a91dc361385ba23e64
So it's very interesting. The base64 data hashed has a 100% success rate, but loading it in Python and in the terminal, resulted in two different hashes. I do not know the reason why even they are different. I do believe what I mentioned earlier in the comments is correct, hashing a file will result in a different hash, as the meta data of the file is hashed too.
In order to provide a solution: try to hash your raw image data, instead of the file. This has the biggest chance of success. Hope this helps.