如何在swift语言中使用CC_MD5方法。

时间:2014-06-09 15:27:25

标签: md5 swift

在objective-c中,我们可以通过以下代码用md5加密字符串

const char *cStr = [someString UTF8String];
unsigned char result[16];
CC_MD5( cStr, strlen(cStr), result );
md5String = [NSString stringWithFormat:
        @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
        result[0], result[1], result[2], result[3],
        result[4], result[5], result[6], result[7],
        result[8], result[9], result[10], result[11],
        result[12], result[13], result[14], result[15]
        ];

但是现在CC_MD5在swift中不起作用。 如何解决这个问题。

9 个答案:

答案 0 :(得分:84)

这就是我想出的。它是String的扩展。 别忘了将#import <CommonCrypto/CommonCrypto.h>添加到Xcode创建的ObjC-Swift桥接头中。

extension String  {
    var md5: String! {
        let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
        let strLen = CC_LONG(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)

        CC_MD5(str!, strLen, result)

        let hash = NSMutableString()
        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }

        result.dealloc(digestLen)

        return String(format: hash as String)
    }
 }

答案 1 :(得分:36)

这是我在Swift 3.0中的版本,我相信它比其他答案更安全,更快。

需要使用#import <CommonCrypto/CommonCrypto.h>的桥接标头。

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])
    }
}

答案 2 :(得分:10)

我将纯粹的Swift实现MD5作为CryptoSwift项目的一部分。

我可以在这里复制代码,但它使用属于此项目一部分的扩展,因此对于复制和粘贴使用可能没用。但是你可以看看并使用它。

答案 3 :(得分:6)

所以这是解决方案,我知道它将节省您的时间100%

<强> BridgingHeader   - &gt;用于将Objective-c代码暴露给Swift项目

<强> CommonCrypto   - &gt;是使用 md5哈希

所需的文件

由于Common Crypto是一个Objective-c文件,你需要使用BridgingHeader来使用散列所需的方法

(例如)

anotations

}

如何将Common Crypto添加到Swift项目中?

link将教你如何(逐步)。

我建议使用桥接标题

*************更新了Swift 3 ****************

extension String {
func md5() -> String! {
    let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
    let strLen = CUnsignedInt(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
    let digestLen = Int(CC_MD5_DIGEST_LENGTH)
    let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
    CC_MD5(str!, strLen, result)
    var hash = NSMutableString()
    for i in 0..<digestLen {
        hash.appendFormat("%02x", result[i])
    }
    result.destroy()
    return String(format: hash as String)
}

如何使用?

让stringConvertedToMD5 =“foo”.toMD5()

答案 4 :(得分:2)

如果你想从NSData中计算出MD5,请看一下:

func md5() -> NSData {
    var ctx = UnsafePointer<CC_MD5_CTX>.alloc(sizeof(CC_MD5_CTX))
    CC_MD5_Init(ctx);

    CC_MD5_Update(ctx, self.bytes, UInt32(self.length));
    let length = Int(CC_MD5_DIGEST_LENGTH) * sizeof(Byte)
    var output = UnsafePointer<Byte>.alloc(length)
    CC_MD5_Final(output, ctx);

    let outData = NSData(bytes: output, length: Int(CC_MD5_DIGEST_LENGTH))
    output.destroy()
    ctx.destroy()

    //withUnsafePointer
    return outData;
}

得到主意。

答案 5 :(得分:2)

Xcode 6 beta 5 现在使用UnsafeMutablePointer代替UnsafePointer。字符串转换还需要format:参数标签。

extension String {
    func md5() -> String! {
        let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
        let strLen = CUnsignedInt(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
        CC_MD5(str!, strLen, result)
        var hash = NSMutableString()
        for i in 0..<digestLen {
            hash.appendFormat("%02x", result[i])
        }
        result.destroy()
        return String(format: hash)
    }
}

答案 6 :(得分:2)

需要将导入#import <CommonCrypto/CommonCrypto.h>导入桥接标题

我正在计算MD5哈希,但只使用我正在使用的前16个字节

class func hash(data: NSData) -> String {

    let data2 = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))!
    CC_MD5(data.bytes, CC_LONG(data.length), UnsafeMutablePointer<UInt8>(data2.mutableBytes))
    let data3 =  UnsafePointer<CUnsignedChar>(data2.bytes)

    var hash = ""
    for (var i = 0; i < 16; ++i) {

        hash +=  String(format: "%02X", data3[i])
    }

    return hash
}

答案 7 :(得分:2)

对于桥接标题不是选项的情况(例如,在shell脚本中),您可以通过+;-使用命令行工具/sbin/md5

NSTask

用法:

import Foundation

func md5hash(string: String) -> String
{
  let t = NSTask()
  t.launchPath = "/sbin/md5"
  t.arguments = ["-q", "-s", string]
  t.standardOutput = NSPipe()

  t.launch()

  let outData = t.standardOutput.fileHandleForReading.readDataToEndOfFile()
  var outBytes = [UInt8](count:outData.length, repeatedValue:0)
  outData.getBytes(&outBytes, length: outData.length)

  var outString = String(bytes: outBytes, encoding: NSASCIIStringEncoding)

  assert(outString != nil, "failed to md5 input string")

  return outString!.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
}

答案 8 :(得分:1)

为了使它在Swift 5中正常工作,我必须对此代码进行一些修复

    func md5(inString: String) -> String! {
    let str = inString.cString(using: String.Encoding.utf8)
    let strLen = CUnsignedInt(inString.lengthOfBytes(using: String.Encoding.utf8))
    let digestLen = Int(CC_MD5_DIGEST_LENGTH)
    let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
    CC_MD5(str!, strLen, result)
    var hash = NSMutableString()
    for i in 0..<digestLen {
        hash.appendFormat("%02x", result[i])
    }
    result.deallocate()
    return String(format: hash as String)
}