Swift 3中的数据MD5

Ond*_*rej 9 md5 swift swift3

我正在尝试获取我的数据的MD5哈希值(从interweb下载的图像).不幸的是我已经将框架升级到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
    }

}
Run Code Online (Sandbox Code Playgroud)

CommonCrypto已作为自定义模块导入.问题是我要'bytes' is unavailable: use withUnsafeBytes instead继续CC_MD5(data.bytes,...

所以问题实际上是,如何从数据中获取字节并且此解决方案是否有效?

Rob*_*ier 15

    CC_MD5(data.bytes, CC_LONG(data.count), &digest)
Run Code Online (Sandbox Code Playgroud)

如上所述,bytes因为它很危险而无法使用.它是进入内存的原始指针而不是消失.建议的解决方案是使用withUnsafeBytes指针范围内目标无法消失的承诺.从内存来看,它看起来像这样:

data.withUnsafeBytes { bytes in
    CC_MD5(bytes, CC_LONG(data.count), &digest)
}
Run Code Online (Sandbox Code Playgroud)

关键是bytes指针不能转移到data不再有效的范围内.

有关此示例,与其CCHmac非常相似MD5,请参阅RNCryptor.


Jus*_*zer 5

这是单行:

import CryptoKit
let md5String = Insecure.MD5.hash(data: data).map { String(format: "%02hhx", $0) }.joined()
Run Code Online (Sandbox Code Playgroud)

对于任何感兴趣的人,这里有一个示例,您可以以此为基础来支持不同的算法:

用法:

Checksum.hash(data: data, using: .md5) == "MyMD5Hash"
Run Code Online (Sandbox Code Playgroud)

代码片段:

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: $0.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)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)