【问题标题】:How to hash a string to SHA512 in Swift?如何在 Swift 中将字符串散列到 SHA512?
【发布时间】:2015-05-17 05:37:15
【问题描述】:

我正在构建一个社交媒体应用程序,我需要一些帮助,将密码字符串编码为 Swift 中的 SHA512。我在 GitHub 上找到了 CryptoSwift 库,但我很难将它加载到我的 Swift 项目中并将其链接到我的项目文件。有谁知道如何相对容易地做到这一点? 提前致谢, 凯尔

【问题讨论】:

标签: swift sha512 cryptoswift


【解决方案1】:

Swift 3 的解决方案:

extension String {

    func sha512() -> String {
        let data = self.data(using: .utf8)!
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
        data.withUnsafeBytes({
            _ = CC_SHA512($0, CC_LONG(data.count), &digest)
        })
        return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
    }

}

【讨论】:

  • 想知道self.data(using: .utf8) 怎么会失败,因为self 必须是有效的String
  • 是的,你是对的。 Swift 字符串总是 unicode 字符串,所以self.data(using: .utf8) 永远不会失败。我相应地调整了我的答案。
  • 在操场上,我必须导入什么才能访问CC_ funcs?基础不够。
  • 无法在 Playground 中直接使用 CommonCrypto,因为您无法添加桥接头。但我读到可以通过在桥接头中添加一个带有 CommonCrypto 的框架:stackoverflow.com/a/42674951/5804550
  • 您好@sundance,感谢您的回答。我不太明白 String(format:) 调用中的“%02hhx”是什么意思;我想知道你能否请你简要解释一下。另外,为什么需要遍历字节并使用 String(format:) 而不是仅使用 base64EncodedString() 将它们转换为字符串?提前致谢
【解决方案2】:

我认为所有的答案都还可以,但如果我们应该有一个真正的通用解决方案,我认为我们需要将其提升一个层次。

CC_LONG 只是一个UInt32,不支持非常大的数据结构。

这是我在 Swift 3 中的解决方案:

首先我们创建一个基础:

struct Sha512 {
    let context = UnsafeMutablePointer<CC_SHA512_CTX>.allocate(capacity:1)

    init() {
        CC_SHA512_Init(context)
    }

    func update(data: Data) {
        data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
            let end = bytes.advanced(by: data.count)
            for f in sequence(first: bytes, next: { $0.advanced(by: Int(CC_LONG.max)) }).prefix(while: { (current) -> Bool in current < end})  {
                _ = CC_SHA512_Update(context, f, CC_LONG(Swift.min(f.distance(to: end), Int(CC_LONG.max))))
            }
        }
    }

    func final() -> Data {
        var digest = [UInt8](repeating: 0, count:Int(CC_SHA512_DIGEST_LENGTH))
        CC_SHA512_Final(&digest, context)

        return Data(bytes: digest)
    }
}

为方便起见,我们为Data 做了一个扩展:

extension Data {
    func sha512() -> Data {
        let s = Sha512()
        s.update(data: self)
        return s.final()
    }
}

最后是String的扩展:

extension String {
    func sha512() -> Data {
        return self.data(using: .utf8)!.sha512()
    }
}

此方案可用于 Sha256、MD5 等,与 Apple 的 CommonCrypto 一起获得良好的真正通用解决方案。

【讨论】:

    【解决方案3】:

    斯威夫特 3

    func sha512() -> String {
        let data = self.data(using: .utf8)!
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
        data.withUnsafeBytes({
            _ = CC_SHA512($0, CC_LONG(data.count), &digest)
        })
    
        return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
    }
    

    斯威夫特 2.3

    func sha512() -> String {
        let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
        var digest = [UInt8](count:Int(CC_SHA512_DIGEST_LENGTH), repeatedValue: 0)
        CC_SHA512(data.bytes, CC_LONG(data.length), &digest)
        let hexBytes = digest.map { String(format: "%02hhx", $0) }
    
        return hexBytes.joinWithSeparator("")
    }
    

    【讨论】:

      【解决方案4】:

      您需要导入 C 库 CommonCrypto。你不能只将 CommonCrypto 导入到你的 swift 文件中,因为它不是一个独立的模块。

      如果你有一个桥接头文件,你是幸运的!只需将其添加到该文件中

      #import <CommonCrypto/CommonCrypto.h>
      

      There are some articles about different ways to do that.

      然后您可以使用这段代码让 sha512 可用于您选择的任何字符串。

      斯威夫特 5

      extension String {
      
          public var sha512: String {
              let data = self.data(using: .utf8) ?? Data()
              var digest = [UInt8](repeating: 0, count: Int(CC_SHA512_DIGEST_LENGTH))
              data.withUnsafeBytes {
                  _ = CC_SHA512($0.baseAddress, CC_LONG(data.count), &digest)
              }
              return digest.map({ String(format: "%02hhx", $0) }).joined(separator: "")
          }
      }
      

      【讨论】:

        【解决方案5】:

        斯威夫特 5

        对于字符串,这个方法对我有用

        func SHA512(string: String) -> String {
            let length = Int(CC_SHA512_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_SHA512(messageBytesBaseAddress, messageLength, digestBytesBlindMemory)
                    }
                    return 0
                }
            }
            return digestData.map { String(format: "%02hhx", $0) }.joined()
        }
        

        如果你只需要数据删除 .map { String(format: "%02hhx", $0):

        func SHA512(string: String) -> Data {
            let length = Int(CC_SHA512_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_SHA512(messageBytesBaseAddress, messageLength, digestBytesBlindMemory)
                    }
                    return 0
                }
            }
            return digestData
        }
        

        【讨论】:

        • 你需要导入CommonCrypto
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-07
        • 1970-01-01
        • 2021-01-08
        • 2011-04-22
        • 2018-12-30
        • 1970-01-01
        相关资源
        最近更新 更多