Xcode 10.2 和 Swift 5
我从相机中选择一个图像,并计算图像的SHA256散列作为字符串,并将图像保存到iPhone相册中。
//Save photo to album. Photo comes from UIImagePickerController
UIImageWriteToSavedPhotosAlbum(self.photo, self, #selector(saveimage(_:didFinishSavingWithError:contextInfo:)), nil)
//Calculate hash
let imageData : Data = self.photo!.pngData()!
let imageHash : String = getImageHash(data: imageData)
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])
}
print(hex)
return hex
}然而,代码给出的图像的SHA256与保存后不同。我将照片传输到Mac,并通过shasum -a 256检查散列,并将其直接从iPhone上传到在线哈希生成器,这给了我与Mac相同的哈希。
因此,我的计算哈希的代码是错误的,或者在使用UIImageWriteToSavedPhotosAlbum(...)存储照片(如名称或属性)时正在更改某些内容。有什么办法解决这个问题吗?
发布于 2019-04-29 08:03:07
我已经对这个问题做了一些进一步的研究,似乎您在UIImage中拥有的数据确实与您作为文件打开的数据不同,我相信这正是造成问题的原因。请注意,为了提高可读性,我缩短了base64数据。
斯威夫特
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
}函数很好,我将使用iOS的资产文件夹使用一个示例。
let imageData = UIImage(named: "Example")!.pngData()!
print(imageData.base64EncodedString())
// 'iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg=='
let imageHash = getImageHash(data: imageData)
print(imageHash)
// '145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397'就我们现在而言,哈希的计算是正确的。我对base64数据很感兴趣,所以我也可以在其他平台上使用它。
Python
import hashlib
import base64
img_d = base64.b64decode('iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg==')
m = hashlib.sha256()
m.update(img_d)
m.digest().hex()
# '145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397'因此,该散列看起来是正确计算的,但仅用于base64数据。那有什么区别呢?让我们再次使用Python进行调查。我使用PIL直接加载图像。
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'因此,现在我们确实有了一个不同的哈希。让我们尝试最后一件事,openssl dgst在终点站。
终端
echo 'iVBORw0KGgoAAAANSUhEUgAAAG8AAACACAQAAACv3v+8AAAM82lD [...] gAAAABJRU5ErkJggg==' | base64 --decode | openssl dgst -sha256
145036245c9f675963cc8de2147887f9feded5813b0539d2320d201d9ce63397好的,实际上,openssl摘要可以计算base64数据上的散列,而且它确实是匹配的。
openssl dgst -sha256 /path/to/file
SHA256(/path/to/file)= d15c2d0c186a46b41c34a312eaf1c7e4b0f7a51bdb9c53a91dc361385ba23e64所以这很有趣。base64数据散列的成功率为100%,但是在Python和终端中加载它,会产生两种不同的哈希。我不知道他们为什么会有所不同。我确实相信我前面在注释中提到的是正确的,哈希文件将导致一个不同的散列,因为文件的元数据也会被散列。
为了提供解决方案:尝试散列原始图像数据,而不是文件。这是最大的成功机会。希望这能有所帮助。
https://stackoverflow.com/questions/55868751
复制相似问题