代码之家  ›  专栏  ›  技术社区  ›  user3606682

如何在iOS中使用Swift将字符串转换为MD5哈希?

  •  138
  • user3606682  · 技术社区  · 9 年前

    我想将“abc”这样的字符串转换为MD5哈希。我想在iOS和Swift中做到这一点。我尝试过使用以下解决方案,但它们不适用于我:

    Importing CommonCrypto in a Swift framework

    How to use CC_MD5 method in swift language.

    http://iosdeveloperzone.com/2014/10/03/using-commoncrypto-in-swift/

    更清楚地说,我想在Swift中实现一个类似于以下PHP代码输出的输出:

    $str = "Hello";
    
    echo md5($str);
    

    输出:8b1A953c4611296a827abf8c47804d7

    19 回复  |  直到 5 年前
        1
  •  199
  •   Repose    5 年前

    有两个步骤:
    1.从字符串创建md5数据
    2.将md5数据转换为十六进制字符串

    Swift 2.0版本:

    func md5(string string: String) -> String {
        var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0)
        if let data = string.dataUsingEncoding(NSUTF8StringEncoding) {
            CC_MD5(data.bytes, CC_LONG(data.length), &digest)
        }
    
        var digestHex = ""
        for index in 0..<Int(CC_MD5_DIGEST_LENGTH) {
            digestHex += String(format: "%02x", digest[index])
        }
    
        return digestHex
    }
    
    //Test:
    let digest = md5(string:"Hello")
    print("digest: \(digest)")
    

    输出:

    摘要:8b1a9953c611296a827abf8c47804d7

    Swift 3.0版本:

    func MD5(string: String) -> Data {
        let messageData = string.data(using:.utf8)!
        var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
    
        _ = digestData.withUnsafeMutableBytes {digestBytes in
            messageData.withUnsafeBytes {messageBytes in
                CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
            }
        }
    
        return digestData
    }
    
    //Test:
    let md5Data = MD5(string:"Hello")
    
    let md5Hex =  md5Data.map { String(format: "%02hhx", $0) }.joined()
    print("md5Hex: \(md5Hex)")
    
    let md5Base64 = md5Data.base64EncodedString()
    print("md5Base64: \(md5Base64)")
    

    输出:

    md5Hex:8b1a9953c4611296a827abf8c47804d7
    md5Base64:ixqZU8RhEpaoJ6v4xHgE1w==

    Swift 5.0版本:

    import Foundation
    import var CommonCrypto.CC_MD5_DIGEST_LENGTH
    import func CommonCrypto.CC_MD5
    import typealias CommonCrypto.CC_LONG
    
    func MD5(string: String) -> Data {
            let length = Int(CC_MD5_DIGEST_LENGTH)
            let messageData = string.data(using:.utf8)!
            var digestData = Data(count: length)
    
            _ = digestData.withUnsafeMutableBytes { digestBytes -> UInt8 in
                messageData.withUnsafeBytes { messageBytes -> UInt8 in
                    if let messageBytesBaseAddress = messageBytes.baseAddress, let digestBytesBlindMemory = digestBytes.bindMemory(to: UInt8.self).baseAddress {
                        let messageLength = CC_LONG(messageData.count)
                        CC_MD5(messageBytesBaseAddress, messageLength, digestBytesBlindMemory)
                    }
                    return 0
                }
            }
            return digestData
        }
    
    //Test:
    let md5Data = MD5(string:"Hello")
    
    let md5Hex =  md5Data.map { String(format: "%02hhx", $0) }.joined()
    print("md5Hex: \(md5Hex)")
    
    let md5Base64 = md5Data.base64EncodedString()
    print("md5Base64: \(md5Base64)")
    

    输出:

    md5Hex:8b1a9953c4611296a827abf8c47804d7
    md5Base64:ixqZU8RhEpaoJ6v4xHgE1w==

    笔记:
    #import <CommonCrypto/CommonCrypto.h> 必须添加到桥接头文件

    有关如何创建桥接标头,请参阅 this SO answer .

    一般来说,MD5不应用于新工作,SHA256是当前的最佳做法。

    不推荐使用的文档部分示例:

    MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384、SHA512(Swift 3+)

    这些函数将使用八种加密哈希算法之一对字符串或数据输入进行哈希。

    name参数将哈希函数名称指定为字符串
    支持的函数有MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384和SHA512 一 此示例需要Common Crypto
    有必要为项目设置一个桥接头:
    #导入<CommonCrypto/CommonCrypto.h>
    添加安全性。项目框架。



    此函数接受要哈希的哈希名称和字符串,并返回数据:

    name: A name of a hash function as a String  
    string: The String to be hashed  
    returns: the hashed result as Data  
    
    func hash(name:String, string:String) -> Data? {
        let data = string.data(using:.utf8)!
        return hash(name:name, data:data)
    }
    

    示例:

    let clearString = "clearData0123456"
    let clearData   = clearString.data(using:.utf8)!
    print("clearString: \(clearString)")
    print("clearData: \(clearData as NSData)")
    
    let hashSHA256 = hash(name:"SHA256", string:clearString)
    print("hashSHA256: \(hashSHA256! as NSData)")
    
    let hashMD5 = hash(name:"MD5", data:clearData)
    print("hashMD5: \(hashMD5! as NSData)")
    

    输出:

    clearString: clearData0123456
    clearData: <636c6561 72446174 61303132 33343536>
    
    hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
    hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>
    
        2
  •  103
  •   Community paulsm4    5 年前

    截至 iOS 13 苹果公司增加了 CryptoKit 框架,因此您不再需要导入CommonCrypto或处理其C API:

    import Foundation
    import CryptoKit
    
    func MD5(string: String) -> String {
        let digest = Insecure.MD5.hash(data: string.data(using: .utf8) ?? Data())
    
        return digest.map {
            String(format: "%02hhx", $0)
        }.joined()
    }
    
    
        3
  •  49
  •   digitalHound    5 年前

    在阅读了这里的其他答案(并且还需要支持其他哈希类型)之后,我编写了一个String扩展,它处理多个哈希类型和输出类型。

    注意:CommonCrypto包含在Xcode 10中,因此您可以简单地 import CommonCrypto 如果安装了最新的Xcode版本,则无需使用桥接头……否则,需要使用桥接头。


    更新:Swift 4&5使用相同的String+Crypto。swift文件。

    有一个单独的数据+密码。swift 5的swift文件(见下文),因为swift 4&5.


    字符串+加密。swift--(用于swift 4和5)

    import Foundation
    import CommonCrypto
    
    // Defines types of hash string outputs available
    public enum HashOutputType {
        // standard hex string output
        case hex
        // base 64 encoded string output
        case base64
    }
    
    // Defines types of hash algorithms available
    public enum HashType {
        case md5
        case sha1
        case sha224
        case sha256
        case sha384
        case sha512
    
        var length: Int32 {
            switch self {
            case .md5: return CC_MD5_DIGEST_LENGTH
            case .sha1: return CC_SHA1_DIGEST_LENGTH
            case .sha224: return CC_SHA224_DIGEST_LENGTH
            case .sha256: return CC_SHA256_DIGEST_LENGTH
            case .sha384: return CC_SHA384_DIGEST_LENGTH
            case .sha512: return CC_SHA512_DIGEST_LENGTH
            }
        }
    }
    
    public extension String {
    
        /// Hashing algorithm for hashing a string instance.
        ///
        /// - Parameters:
        ///   - type: The type of hash to use.
        ///   - output: The type of output desired, defaults to .hex.
        /// - Returns: The requested hash output or nil if failure.
        public func hashed(_ type: HashType, output: HashOutputType = .hex) -> String? {
    
            // convert string to utf8 encoded data
            guard let message = data(using: .utf8) else { return nil }
            return message.hashed(type, output: output)
        } 
    }
    

    雨燕5 --数据+Crypto.swift

    import Foundation
    import CommonCrypto
    
    extension Data {
    
        /// Hashing algorithm that prepends an RSA2048ASN1Header to the beginning of the data being hashed.
        ///
        /// - Parameters:
        ///   - type: The type of hash algorithm to use for the hashing operation.
        ///   - output: The type of output string desired.
        /// - Returns: A hash string using the specified hashing algorithm, or nil.
        public func hashWithRSA2048Asn1Header(_ type: HashType, output: HashOutputType = .hex) -> String? {
    
            let rsa2048Asn1Header:[UInt8] = [
                0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
                0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
            ]
    
            var headerData = Data(rsa2048Asn1Header)
            headerData.append(self)
    
            return hashed(type, output: output)
        }
    
        /// Hashing algorithm for hashing a Data instance.
        ///
        /// - Parameters:
        ///   - type: The type of hash to use.
        ///   - output: The type of hash output desired, defaults to .hex.
        ///   - Returns: The requested hash output or nil if failure.
        public func hashed(_ type: HashType, output: HashOutputType = .hex) -> String? {
    
            // setup data variable to hold hashed value
            var digest = Data(count: Int(type.length))
    
            _ = digest.withUnsafeMutableBytes{ digestBytes -> UInt8 in
                self.withUnsafeBytes { messageBytes -> UInt8 in
                    if let mb = messageBytes.baseAddress, let db = digestBytes.bindMemory(to: UInt8.self).baseAddress {
                        let length = CC_LONG(self.count)
                        switch type {
                        case .md5: CC_MD5(mb, length, db)
                        case .sha1: CC_SHA1(mb, length, db)
                        case .sha224: CC_SHA224(mb, length, db)
                        case .sha256: CC_SHA256(mb, length, db)
                        case .sha384: CC_SHA384(mb, length, db)
                        case .sha512: CC_SHA512(mb, length, db)
                        }
                    }
                    return 0
                }
            }
    
            // return the value based on the specified output type.
            switch output {
            case .hex: return digest.map { String(format: "%02hhx", $0) }.joined()
            case .base64: return digest.base64EncodedString()
            }
        }
    }
    

    雨燕4 --数据+Crypto.swift

    import Foundation
    import CommonCrypto 
    
    extension Data {
    
        /// Hashing algorithm that prepends an RSA2048ASN1Header to the beginning of the data being hashed.
        ///
        /// - Parameters:
        ///   - type: The type of hash algorithm to use for the hashing operation.
        ///   - output: The type of output string desired.
        /// - Returns: A hash string using the specified hashing algorithm, or nil.
        public func hashWithRSA2048Asn1Header(_ type: HashType, output: HashOutputType = .hex) -> String? {
    
            let rsa2048Asn1Header:[UInt8] = [
                0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
                0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00
            ]
    
            var headerData = Data(bytes: rsa2048Asn1Header)
            headerData.append(self)
    
            return hashed(type, output: output)
        }
    
        /// Hashing algorithm for hashing a Data instance.
        ///
        /// - Parameters:
        ///   - type: The type of hash to use.
        ///   - output: The type of hash output desired, defaults to .hex.
        ///   - Returns: The requested hash output or nil if failure.
        public func hashed(_ type: HashType, output: HashOutputType = .hex) -> String? {
    
            // setup data variable to hold hashed value
            var digest = Data(count: Int(type.length))
    
            // generate hash using specified hash type
            _ = digest.withUnsafeMutableBytes { (digestBytes: UnsafeMutablePointer<UInt8>) in
                self.withUnsafeBytes { (messageBytes: UnsafePointer<UInt8>) in
                    let length = CC_LONG(self.count)
                    switch type {
                    case .md5: CC_MD5(messageBytes, length, digestBytes)
                    case .sha1: CC_SHA1(messageBytes, length, digestBytes)
                    case .sha224: CC_SHA224(messageBytes, length, digestBytes)
                    case .sha256: CC_SHA256(messageBytes, length, digestBytes)
                    case .sha384: CC_SHA384(messageBytes, length, digestBytes)
                    case .sha512: CC_SHA512(messageBytes, length, digestBytes)
                    }
                }
            }
    
            // return the value based on the specified output type.
            switch output {
            case .hex: return digest.map { String(format: "%02hhx", $0) }.joined()
            case .base64: return digest.base64EncodedString()
            }
        }
    }
    

    编辑:由于哈希实际上发生在Data上,我将哈希算法拆分为Data扩展。这允许同样的算法也用于SSL证书固定哈希操作。

    下面是一个简短的示例,说明如何将其用于SSL Pinning操作:

    // Certificate pinning - get certificate as data
    let data: Data = SecCertificateCopyData(serverCertificate) as Data
    
    // compare hash of server certificate with local (expected) hash value
    guard let serverHash = data.hashWithRSA2048Asn1Header(.sha256, output: .base64), serverHash == storedHash else {
        print("SSL PINNING: Server certificate hash does not match specified hash value.")
        return false
    }
    

    回到原来的答案

    我用这个测试了哈希算法:

    let value = "This is my string"
    
    if let md5 = value.hashed(.md5) {
        print("md5: \(md5)")
    }
    if let sha1 = value.hashed(.sha1) {
        print("sha1: \(sha1)")
    }
    if let sha224 = value.hashed(.sha224) {
        print("sha224: \(sha224)")
    }
    if let sha256 = value.hashed(.sha256) {
        print("sha256: \(sha256)")
    }
    if let sha384 = value.hashed(.sha384) {
        print("sha384: \(sha384)")
    }
    if let sha512 = value.hashed(.sha512) {
        print("sha512: \(sha512)")
    }
    

    这是打印结果:

    md5: c2a9ce57e8df081b4baad80d81868bbb
    sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223
    sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7
    sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b
    sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450
    sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883
    
        4
  •  28
  •   Wajih    8 年前

    SWIFT 3 的版本 md5 function :

    func md5(_ string: String) -> String {
    
        let context = UnsafeMutablePointer<CC_MD5_CTX>.allocate(capacity: 1)
        var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5_Init(context)
        CC_MD5_Update(context, string, CC_LONG(string.lengthOfBytes(using: String.Encoding.utf8)))
        CC_MD5_Final(&digest, context)
        context.deallocate(capacity: 1)
        var hexString = ""
        for byte in digest {
            hexString += String(format:"%02x", byte)
        }
    
        return hexString
    }
    

    原始链接来自 http://iosdeveloperzone.com

        5
  •  25
  •   Invictus Cody    6 年前

    Swift 4.*,Xcode 10更新:

    在Xcode 10中,您不必使用 桥接集管 此外,您还可以使用

    import CommonCrypto
    

    然后写一个类似的方法:

    func MD5(_ string: String) -> String? {
            let length = Int(CC_MD5_DIGEST_LENGTH)
            var digest = [UInt8](repeating: 0, count: length)
    
            if let d = string.data(using: String.Encoding.utf8) {
                _ = d.withUnsafeBytes { (body: UnsafePointer<UInt8>) in
                    CC_MD5(body, CC_LONG(d.count), &digest)
                }
            }
    
            return (0..<length).reduce("") {
                $0 + String(format: "%02x", digest[$1])
            }
        }
    

    用法:

    MD5("This is my string")
    

    输出:

    c2a9ce57e8df081b4baad80d81868bbb
    
        6
  •  21
  •   Nikolai Ruhe    6 年前

    我发布了 pure Swift implementation 它不依赖于CommonCrypto或其他任何东西。它在麻省理工学院许可证下可用。

    代码由一个 single swift file 你可以直接加入你的项目。如果您愿意,还可以将包含的Xcode项目与框架和单元测试目标一起使用。

    使用简单:

    let input = "The quick brown fox jumps over the lazy dog"
    let digest = input.utf8.md5
    print("md5: \(digest)")
    

    打印: md5: 9e107d9d372bb6826bd81d3542a419d6

    swift文件包含文档和更多示例。

        7
  •  20
  •   Radu Ursache    4 年前

    在里面 雨燕5.3 你能做到的

    import CryptoKit
    
    func md5Hash(_ source: String) -> String {
        return Insecure.MD5.hash(data: source.data(using: .utf8)!).map { String(format: "%02hhx", $0) }.joined()
    }
    
        8
  •  10
  •   Community paulsm4    7 年前

    这里只有两个注释:

    使用 加密 实现这一点的开销太大了。

    这个 accepted answer 是完美的!然而,我只想分享一个 敏捷的 伊埃 代码方法使用 斯威夫特2.2 .

    请记住,您仍然必须 #import <CommonCrypto/CommonCrypto.h> 在您的 桥接集管 文件

    struct MD5Digester {
        // return MD5 digest of string provided
        static func digest(string: String) -> String? {
    
            guard let data = string.dataUsingEncoding(NSUTF8StringEncoding) else { return nil }
    
            var digest = [UInt8](count: Int(CC_MD5_DIGEST_LENGTH), repeatedValue: 0)
    
            CC_MD5(data.bytes, CC_LONG(data.length), &digest)
    
            return (0..<Int(CC_MD5_DIGEST_LENGTH)).reduce("") { $0 + String(format: "%02x", digest[$1]) }
        }
    }
    
        9
  •  9
  •   glyvox    5 年前

    雨燕5 答案为字符串扩展名(基于 the great answer of Invictus Cody ):

    import CommonCrypto
    
    extension String {
        var md5Value: String {
            let length = Int(CC_MD5_DIGEST_LENGTH)
            var digest = [UInt8](repeating: 0, count: length)
    
            if let d = self.data(using: .utf8) {
                _ = d.withUnsafeBytes { body -> String in
                    CC_MD5(body.baseAddress, CC_LONG(d.count), &digest)
    
                    return ""
                }
            }
    
            return (0 ..< length).reduce("") {
                $0 + String(format: "%02x", digest[$1])
            }
        }
    }
    

    用法:

    print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
    
        10
  •  6
  •   Glaubenio Patricio    7 年前

    这是基于zaph答案的扩展

    extension String{
        var MD5:String {
            get{
                let messageData = self.data(using:.utf8)!
                var digestData = Data(count: Int(CC_MD5_DIGEST_LENGTH))
    
                _ = digestData.withUnsafeMutableBytes {digestBytes in
                    messageData.withUnsafeBytes {messageBytes in
                        CC_MD5(messageBytes, CC_LONG(messageData.count), digestBytes)
                    }
                }
    
                return digestData.map { String(format: "%02hhx", $0) }.joined()
            }
        }
    }
    

    与swift 3.0完全兼容。您仍然需要 #import <CommonCrypto/CommonCrypto.h> 在桥接头文件中

        11
  •  4
  •   Rahul K Rajan    5 年前

    在swift编程中,最好使用字符串函数,因此使用起来很容易。 在这里,我使用上面给出的解决方案之一制作了一个字符串扩展。谢谢@wajih

    import Foundation
    import CommonCrypto
    
    extension String {
    
    func md5() -> String {
    
        let context = UnsafeMutablePointer<CC_MD5_CTX>.allocate(capacity: 1)
        var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5_Init(context)
        CC_MD5_Update(context, self, CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8)))
        CC_MD5_Final(&digest, context)
        context.deallocate()
        var hexString = ""
        for byte in digest {
            hexString += String(format:"%02x", byte)
        }
    
        return hexString
    }
    }
    

    用法

    let md5String = "abc".md5()
    
        12
  •  4
  •   palme    3 年前

    Swift 5.3:基于@Radu Ursache和@mluisbrown答案:字符串的简单扩展

    import CryptoKit
    
    extension String {
        func md5() -> String {
            return Insecure.MD5.hash(data: self.data(using: .utf8)!).map { String(format: "%02hhx", $0) }.joined()
        }
    }
    

    用法:

    "My awesome String".md5()
    
        13
  •  3
  •   siki    4 年前
    import CryptoKit
    private func MD5Base64(_ string: String) -> String {
        let digest = Insecure.MD5.hash(data: string.data(using: .utf8) ?? Data())
        let digestString = digest.map { String(format: "%02hhx", $0) }.joined()
        return digestString.toBase64()
    }
    
    extension String {
        func toBase64() -> String {
            return Data(self.utf8).base64EncodedString()
        }
    }
    
        14
  •  2
  •   Vyacheslav    5 年前

    答案 雨燕5 有适当的内存管理,没有 String 方法内的类:

    typealias CBridgeCryptoMethodType = (UnsafeRawPointer?,
                                     UInt32,
                                     UnsafeMutablePointer<UInt8>?)
    -> UnsafeMutablePointer<UInt8>?
    
    private enum HashType {
    
        // MARK: - Cases
    
        case md5
        case sha1
        case sha224
        case sha256
        case sha384
        case sha512
    }
    
    extension Data {
        var hexString: String {
            let localHexString = reduce("", { previous, current in
                return previous + String(format: "%02X", current)
            })
            return localHexString
        }
        var md5: Data {
            return hashed(for: .md5)
        }
        var sha1: Data {
            return hashed(for: .sha1)
        }
        var sha224: Data {
            return hashed(for: .sha224)
        }
        var sha256: Data {
            return hashed(for: .sha256)
        }
        var sha384: Data {
            return hashed(for: .sha384)
        }
        var sha512: Data {
            return hashed(for: .sha512)
        }
    
        private func hashed(for hashType: HashType) -> Data {
            return withUnsafeBytes { (rawBytesPointer: UnsafeRawBufferPointer) -> Data in
                guard let bytes = rawBytesPointer.baseAddress?.assumingMemoryBound(to: Float.self) else {
                    return Data()
                }
                let hashMethod: CBridgeCryptoMethodType
                let digestLength: Int
                switch hashType {
                case .md5:
                    hashMethod = CC_MD5
                    digestLength = Int(CC_MD5_DIGEST_LENGTH)
                case .sha1:
                    hashMethod = CC_SHA1
                    digestLength = Int(CC_SHA1_DIGEST_LENGTH)
                case .sha224:
                    hashMethod = CC_SHA224
                    digestLength = Int(CC_SHA224_DIGEST_LENGTH)
                case .sha256:
                    hashMethod = CC_SHA256
                    digestLength = Int(CC_SHA256_DIGEST_LENGTH)
                case .sha384:
                    hashMethod = CC_SHA384
                    digestLength = Int(CC_SHA384_DIGEST_LENGTH)
                case .sha512:
                    hashMethod = CC_SHA512
                    digestLength = Int(CC_SHA512_DIGEST_LENGTH)
                }
                let result = UnsafeMutablePointer<UInt8>.allocate(capacity: digestLength)
                _ = hashMethod(bytes, CC_LONG(count), result)
                let md5Data = Data(bytes: result, count: digestLength)
                result.deallocate()
                return md5Data
            }
        }
    }
    

    实例

    let str = "The most secure string ever"
    print("md5", str.data(using: .utf8)?.md5.hexString)
    print("sha1", str.data(using: .utf8)?.sha1.hexString)
    print("sha224", str.data(using: .utf8)?.sha224.hexString)
    print("sha256", str.data(using: .utf8)?.sha256.hexString)
    print("sha384", str.data(using: .utf8)?.sha384.hexString)
    print("sha512", str.data(using: .utf8)?.sha512.hexString)
    

    结果:

    md5可选(“671C121427F12FBBA66CEE71C4CB62C”)

    sha1可选(“A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA”)

    沙224 可选(“334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE”)

    沙256 可选(“8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D”)

    沙384 可选(“04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E”)

    沙512 可选(“1D595EAFEB22162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86A68”)

        15
  •  1
  •   Keith John Hutchison    9 年前

    我用迦太基和昔普托来做这件事。

    1. Install Carthage if you've not already done so

    2. Install Crypto into your project

    3. 执行“cartage update”

    4. 如果从命令行运行,请在swift文件中添加框架

      #!/usr/bin/env xcrun swift -F Carthage/Build/Mac
      
    5. 将import Crypto添加到swift文件中。

    6. 那么它就起作用了!

      print( "convert this".MD5 )
      
        16
  •  1
  •   Nagendra Rao ivaneliasoo    6 年前

    MD5是一种哈希算法,无需为此使用庞大的CommonCrypto库(并被苹果审查拒绝),只需使用任何MD5哈希库即可。

    我使用的一个这样的库是 SwiftHash ,MD5的纯快速实现(基于 http://pajhome.org.uk/crypt/md5/md5.html )

        17
  •  1
  •   Monsoir    5 年前

    基于 Cody's solution ,我有一个想法,我们应该澄清MD5的结果是什么,因为我们可以将结果用作十六进制字符串或Base64字符串。

    func md5(_ string: String) -> [UInt8] {
        let length = Int(CC_MD5_DIGEST_LENGTH)
        var digest = [UInt8](repeating: 0, count: length)
    
        if let d = string.data(using: String.Encoding.utf8) {
            _ = d.withUnsafeBytes { (body: UnsafePointer<UInt8>) in
                CC_MD5(body, CC_LONG(d.count), &digest)
            }
        }
        return digest
    }
    

    上面的函数实际上返回一个 [UInt8] ,并且基于此结果,我们可以获得任何形式的字符串,例如十六进制、base64。

    如果需要十六进制字符串作为最终结果(如问题所问),我们可以继续使用 科迪解

    extension String {
        var md5Hex: String {
            let length = Int(CC_MD5_DIGEST_LENGTH)
            return (0..<length).reduce("") {
                $0 + String(format: "%02x", digest[$1])
            }
        }
    }
    

    如果需要Base64字符串作为最终结果

    extension String {
        var md5Base64: String {
            let md5edData = Data(bytes: md5(self))
            return md5edData.base64EncodedString()
        }
    }
    
        18
  •  0
  •   Edmund Lee    6 年前

    我发现这个图书馆似乎工作得很好。

    https://github.com/onmyway133/SwiftHash

    MD5("string")
    
        19
  •  0
  •   ingconti    5 年前

    我的两美分(如果你需要快速md5 数据 /NSData,例如您下载或读取磁盘或网络的二进制文件)

    (无耻地来自“Swift 5答案作为字符串扩展(基于Invictus Cody的伟大答案)”):

    extension Data {
        var md5Value: String {
            let length = Int(CC_MD5_DIGEST_LENGTH)
            var digest = [UInt8](repeating: 0, count: length)
    
            _ = self.withUnsafeBytes { body -> String in
                CC_MD5(body.baseAddress, CC_LONG(self.count), &digest)
                return ""
            }
    
    
            return (0 ..< length).reduce("") {
                $0 + String(format: "%02x", digest[$1])
            }
        }
    } 
    

    测试:

    print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/