Swift 3 中数据的 MD5
MD5 of Data in Swift 3
我正在尝试获取我的数据(从互联网下载的图片)的 MD5 哈希值。不幸的是,我已经将框架升级到 swift 3,我一直使用的方法现在不起作用。
我已经转换了大部分,但我无法从数据中获取字节:
import Foundation
import CommonCrypto
struct MD5 {
static func get(data: Data) -> String {
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
CC_MD5(data.bytes, CC_LONG(data.count), &digest)
var digestHex = ""
for index in 0..<Int(CC_MD5_DIGEST_LENGTH) {
digestHex += String(format: "%02x", digest[index])
}
return digestHex
}
}
CommonCrypto 已作为自定义模块导入。问题是我在 CC_MD5(data.bytes,...
上得到 'bytes' is unavailable: use withUnsafeBytes instead
所以真正的问题是,我如何从数据中获取字节,这个解决方案是否有效?
CC_MD5(data.bytes, CC_LONG(data.count), &digest)
如前所述,bytes
不可用,因为它很危险。它是指向内存的原始指针,不会消失。推荐的解决方案是使用 withUnsafeBytes
,它保证目标不会在指针范围内消失。根据记忆,它看起来像这样:
data.withUnsafeBytes { bytes in
CC_MD5(bytes, CC_LONG(data.count), &digest)
}
重点是 bytes
指针无法转义到 data
不再有效的范围内。
有关 CCHmac
的示例,它与 MD5
非常相似,请参阅 RNCryptor。
这是一个衬垫:
import CryptoKit
let md5String = Insecure.MD5.hash(data: data).map { String(format: "%02hhx", [=10=]) }.joined()
对于任何感兴趣的人,这里有一个示例,您可以在此基础上支持不同的算法:
用法:
Checksum.hash(data: data, using: .md5) == "MyMD5Hash"
代码片段:
import Foundation
import CommonCrypto
struct Checksum {
private init() {}
static func hash(data: Data, using algorithm: HashAlgorithm) -> String {
/// Creates an array of unsigned 8 bit integers that contains zeros equal in amount to the digest length
var digest = [UInt8](repeating: 0, count: algorithm.digestLength())
/// Call corresponding digest calculation
data.withUnsafeBytes {
algorithm.digestCalculation(data: [=12=].baseAddress, len: UInt32(data.count), digestArray: &digest)
}
var hashString = ""
/// Unpack each byte in the digest array and add them to the hashString
for byte in digest {
hashString += String(format:"%02x", UInt8(byte))
}
return hashString
}
/**
* Hash using CommonCrypto
* API exposed from CommonCrypto-60118.50.1:
* https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60118.50.1/include/CommonDigest.h.auto.html
**/
enum HashAlgorithm {
case md5
case sha256
func digestLength() -> Int {
switch self {
case .md5:
return Int(CC_MD5_DIGEST_LENGTH)
case .sha256:
return Int(CC_SHA256_DIGEST_LENGTH)
}
}
/// CC_[HashAlgorithm] performs a digest calculation and places the result in the caller-supplied buffer for digest
/// Calls the given closure with a pointer to the underlying unsafe bytes of the data's contiguous storage.
func digestCalculation(data: UnsafeRawPointer!, len: UInt32, digestArray: UnsafeMutablePointer<UInt8>!) {
switch self {
case .md5:
CC_MD5(data, len, digestArray)
case .sha256:
CC_SHA256(data, len, digestArray)
}
}
}
}
我正在尝试获取我的数据(从互联网下载的图片)的 MD5 哈希值。不幸的是,我已经将框架升级到 swift 3,我一直使用的方法现在不起作用。
我已经转换了大部分,但我无法从数据中获取字节:
import Foundation
import CommonCrypto
struct MD5 {
static func get(data: Data) -> String {
var digest = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
CC_MD5(data.bytes, CC_LONG(data.count), &digest)
var digestHex = ""
for index in 0..<Int(CC_MD5_DIGEST_LENGTH) {
digestHex += String(format: "%02x", digest[index])
}
return digestHex
}
}
CommonCrypto 已作为自定义模块导入。问题是我在 CC_MD5(data.bytes,...
'bytes' is unavailable: use withUnsafeBytes instead
所以真正的问题是,我如何从数据中获取字节,这个解决方案是否有效?
CC_MD5(data.bytes, CC_LONG(data.count), &digest)
如前所述,bytes
不可用,因为它很危险。它是指向内存的原始指针,不会消失。推荐的解决方案是使用 withUnsafeBytes
,它保证目标不会在指针范围内消失。根据记忆,它看起来像这样:
data.withUnsafeBytes { bytes in
CC_MD5(bytes, CC_LONG(data.count), &digest)
}
重点是 bytes
指针无法转义到 data
不再有效的范围内。
有关 CCHmac
的示例,它与 MD5
非常相似,请参阅 RNCryptor。
这是一个衬垫:
import CryptoKit
let md5String = Insecure.MD5.hash(data: data).map { String(format: "%02hhx", [=10=]) }.joined()
对于任何感兴趣的人,这里有一个示例,您可以在此基础上支持不同的算法:
用法:
Checksum.hash(data: data, using: .md5) == "MyMD5Hash"
代码片段:
import Foundation
import CommonCrypto
struct Checksum {
private init() {}
static func hash(data: Data, using algorithm: HashAlgorithm) -> String {
/// Creates an array of unsigned 8 bit integers that contains zeros equal in amount to the digest length
var digest = [UInt8](repeating: 0, count: algorithm.digestLength())
/// Call corresponding digest calculation
data.withUnsafeBytes {
algorithm.digestCalculation(data: [=12=].baseAddress, len: UInt32(data.count), digestArray: &digest)
}
var hashString = ""
/// Unpack each byte in the digest array and add them to the hashString
for byte in digest {
hashString += String(format:"%02x", UInt8(byte))
}
return hashString
}
/**
* Hash using CommonCrypto
* API exposed from CommonCrypto-60118.50.1:
* https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60118.50.1/include/CommonDigest.h.auto.html
**/
enum HashAlgorithm {
case md5
case sha256
func digestLength() -> Int {
switch self {
case .md5:
return Int(CC_MD5_DIGEST_LENGTH)
case .sha256:
return Int(CC_SHA256_DIGEST_LENGTH)
}
}
/// CC_[HashAlgorithm] performs a digest calculation and places the result in the caller-supplied buffer for digest
/// Calls the given closure with a pointer to the underlying unsafe bytes of the data's contiguous storage.
func digestCalculation(data: UnsafeRawPointer!, len: UInt32, digestArray: UnsafeMutablePointer<UInt8>!) {
switch self {
case .md5:
CC_MD5(data, len, digestArray)
case .sha256:
CC_SHA256(data, len, digestArray)
}
}
}
}