Swift 3中数据的MD5

Swift 3中数据的MD5,swift,md5,swift3,Swift,Md5,Swift3,我正在尝试获取我的数据(从interweb下载的图像)的MD5哈希。不幸的是,我已经将框架升级到swift 3,并且我一直使用的方法现在不起作用 我已转换了大部分数据,但无法从数据中提取字节: import Foundation import CommonCrypto struct MD5 { static func get(data: Data) -> String { var digest = [UInt8](repeating: 0, count: In

我正在尝试获取我的数据(从interweb下载的图像)的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
    }

}
<代码>导入基础 导入通用加密 结构MD5{ 静态func get(数据:数据)->String{ var digest=[UInt8](重复:0,计数:Int(CC_MD5_digest_LENGTH)) CC_MD5(data.bytes、CC_LONG(data.count)和摘要) var digestHex=“” 对于0中的索引。。 如前所述,
字节
不可用,因为它很危险。它是内存中的原始指针,可能会消失。建议的解决方案是使用
withUnsafeBytes
,它承诺目标在指针作用域内不会消失。从内存中看,它类似于:

data.withUnsafeBytes { bytes in
    CC_MD5(bytes, CC_LONG(data.count), &digest)
}
关键是
字节
指针无法转义到
数据
不再有效的范围中

有关
CCHmac
的示例,它与
MD5
非常相似,请参阅。

这里有一条直线:

import CryptoKit
let md5String = Insecure.MD5.hash(data: data).map { String(format: "%02hhx", $0) }.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: $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)
            }
        }
    }
}
<代码>导入基础 导入通用加密 结构校验和{ 私有init(){} 静态func哈希(数据:数据,使用算法:HashAlgorithm)->字符串{ ///创建一个无符号8位整数数组,其中包含等于摘要长度的零 var digest=[UInt8](重复:0,计数:algorithm.digestLength()) ///调用相应的摘要计算 data.withUnsafeBytes{ 算法.digestCalculation(数据:$0.baseAddress,len:UInt32(data.count),digestArray:&digest) } var hashString=“” ///解压缩摘要数组中的每个字节,并将它们添加到哈希字符串中 对于摘要中的字节{ hashString+=字符串(格式:“%02x”,UInt8(字节)) } 返回哈希字符串 } /** *使用CommonCrypto的哈希 *从CommonCrypto-60118.50.1中暴露的API: * https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60118.50.1/include/CommonDigest.h.auto.html **/ 枚举哈希算法{ 案例md5 案例sha256 func digestLength()->Int{ 切换自身{ 案例5: 返回整数(抄送MD5摘要长度) 案例256: 返回整数(抄送长度) } } ///CC_u2;[HashAlgorithm]执行摘要计算,并将结果放入调用者提供的摘要缓冲区中 ///使用指向数据连续存储的底层不安全字节的指针调用给定的闭包。 func digestCalculation(数据:UnsafeRawPointer!,len:UInt32,digestArray:UnsafeMutablePointer!){ 切换自身{ 案例5: CC_MD5(数据、len、digestArray) 案例256: CC_SHA256(数据、len、digestArray) } } } }
我寻找这个答案的时间太长了!谢谢你Swift是我使用过的最差语言之一的另一个原因:为什么不简单地使用md5(blah:AnyObject)->String:(你建议的语法非常模糊,会导致严重的混乱。)(与我经常遇到的开发人员一样,他们试图在PHP和JavaScript中执行哈希运算,却得到了意外和错误的结果,我必须引导他们进行修复)。但是,是的,如果这不是从C神奇地桥接而来的,并且有一个正确的Swift接口,你是正确的,它永远不会像这样(因为这种神奇的桥接语法非常难看)。它将是一个简单的数据方法,并将返回一个数据。可能是Data.md5Hashed()或类似的。这是一个不需要CommonCrypto的方法。
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)
            }
        }
    }
}