web-dev-qa-db-fra.com

Comment utiliser la méthode CC_MD5 en langue Swift.

dans objective-c, nous pouvons chiffrer une chaîne avec md5 avec les codes suivants

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]
        ];

mais maintenant, CC_MD5 ne fonctionne pas dans Swift .. Comment gérer cela.

44
Suen

C'est ce que je suis venu avec. C'est une extension de String . N'oubliez pas d'ajouter #import <CommonCrypto/CommonCrypto.h> à l'en-tête de pont ObjC-Swift créé par Xcode.

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)
    }
 }
82
Jernej Strasner

Voici ma version dans Swift 3.0, je crois que c'est plus sûr et plus rapide que les autres réponses ici.

Un en-tête de pontage avec #import <CommonCrypto/CommonCrypto.h> est requis.

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

J'ai implémenté purement Swift de MD5 dans le cadre de CryptoSwift project.

Je pourrais copier le code ici, mais il utilise des extensions qui font partie de ce projet, ce qui le rend inutile pour une utilisation copier-coller. Cependant, vous pouvez y jeter un coup d'œil et l'utiliser.

10
Marcin

Voici donc la solution et je sais que cela fera économiser votre temps à 100%

BridgingHeader -> Utilisé pour Expose le code Objective-c dans un projet Swift

CommonCrypto -> est le fichier nécessaire pour utiliser md5 hash

Common Crypto étant un fichier Objective-c, vous devez utiliser BridgingHeader pour utiliser la méthode nécessaire au hachage.


(par exemple)

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

}

Comment ajouter Common Crypto à un projet Swift?

Ce link vous apprendra comment (STEP by STEP).

Je recommande d'utiliser Bridging Header

************* Mise à jour Swift 3 *****************

extension String {
func toMD5()  -> String {

        if let messageData = self.data(using:String.Encoding.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.hexString()
        }

        return self
    }
}


extension Data {

    func hexString() -> String {
        let string = self.map{ String($0, radix:16) }.joined()
        return string
    }

}

Comment utiliser?

laissez stringConvertedToMD5 = "foo" .toMD5 ()

6
Basil Mariano

Besoin d'importer #import <CommonCrypto/CommonCrypto.h> dans Bridging Header

Je calcule le hachage MD5, mais je n'utilise que les 16 premiers octets.

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
}
2
János

si vous voulez calculer MD5 à partir de NSData, jetez un coup d’œil à ceci: 

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;
}

pour avoir une idée.

2
Marcin

Dans les cas où l'en-tête de pontage n'est pas une option (par exemple, dans un script Shell), vous pouvez utiliser l'outil de ligne de commande /sbin/md5 via 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())
}

Usage:

let md5 = md5hash("hello world")

// 5eb63bbbe01eeed093cb22bb8f5acdc3
2
Abhi Beckert

Xcode 6 beta 5 utilise maintenant une UnsafeMutablePointer à la place de UnsafePointer. La conversion de chaîne nécessite également le libellé de l'argument 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)
    }
}
2
Dan Greenfield

Voici quelques corrections que j'ai dû apporter à ce code pour le faire fonctionner dans 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)
}
0
Vijay Kumar A B