wake-up-neo.net

So konvertieren Sie einen String in MD5-Hash mit ios swift

Ich möchte Benutzereingaben konvertieren oder eine beliebige Zeichenfolge wie "abc" in MD5-Hash übernehmen. Ich möchte dies in ios Swift tun. Ich habe auf die folgenden Links verwiesen, aber die Lösungen funktionieren nicht für mich oder ich bin verwirrt, wenn ich es richtig mache. Könnte mir jemand mit klaren Schritten dabei helfen? Danke im Voraus!

CommonCrypto in einem Swift-Framework importieren

So verwenden Sie die Methode CC_MD5 in der Sprache Swift.

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

Um klarer zu sein, möchte ich dies in Swift erreichen, wie wir es in PHP tun.

$str = "Hello";

echo md5($str);

Ausgabe: 8b1a9953c4611296a827abf8c47804d7

71
user3606682

Es gibt zwei Schritte:
1. Erstellen Sie MD5-Daten aus einer Zeichenfolge
2. Konvertieren Sie die MD5-Daten in einen Hex-String 

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

Ausgabe: 

digest: 8b1a9953c4611296a827abf8c47804d7

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

Ausgabe: 

md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w ==

Anmerkungen:
#import <CommonCrypto/CommonCrypto.h> muss einer Bridging-Header-Datei hinzugefügt werden

Wie Sie einen Bridging-Header erstellen, erfahren Sie unter dieser SO Antwort .

Im Allgemeinen sollte MD5 nicht für neue Arbeiten verwendet werden. SHA256 ist eine gängige Best Practice.

Beispiel aus dem veralteten Dokumentationsabschnitt:

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

Diese Funktionen werden entweder mit einer von acht kryptographischen Hash-Algorithmen als Zeichenfolge oder mit einer Dateneingabe gehasht.

Der name-Parameter gibt den Hash-Funktionsnamen als String an
Unterstützte Funktionen sind MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384 und SHA512 A Dieses Beispiel erfordert Common Crypto
Es ist notwendig, einen Brückenkopf zum Projekt zu haben:
#import <CommonCrypto/CommonCrypto.h>
Fügen Sie das Security.framework dem Projekt hinzu. 



Diese Funktion benötigt einen Hashnamen und eine Zeichenfolge, die gehasht werden sollen, und gibt Daten zurück:

 name: Der Name einer Hash-Funktion als String 
 string: Der zu hashende String 
 gibt das Hash-Ergebnis als Data .__ zurück.
func hash(name:String, string:String) -> Data? {
    let data = string.data(using:.utf8)!
    return hash(name:name, data:data)
}

Beispiele:

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

Ausgabe:

clearString: clearData0123456
clearData: <636c6561 72446174 61303132 33343536>

hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>
127
zaph

Swift 3 version von 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
}

Ursprünglicher Link von http://iosdeveloperzone.com

25
wajih

Ich habe eine pure Swift-Implementierung veröffentlicht, die nicht von CommonCrypto oder irgendetwas anderem abhängig ist. Es ist unter der Lizenz MIT verfügbar.

Der Code besteht aus einer einzelnen Swift-Datei , die Sie einfach in Ihr Projekt einfügen können. Wenn Sie möchten, können Sie das enthaltene Xcode-Projekt auch mit Framework- und Komponententestzielen verwenden.

Es ist einfach zu benutzen:

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

druckt: md5: 9e107d9d372bb6826bd81d3542a419d6

Die Swift-Datei enthält Dokumentation und weitere Beispiele.

16
Nikolai Ruhe

Nachdem ich die anderen Antworten hier gelesen hatte (und auch andere Hashtypen unterstützen musste), schrieb ich eine String-Erweiterung, die mehrere Hashtypen und Ausgabetypen behandelt.

HINWEIS: CommonCrypto ist in Xcode 10 enthalten. Sie können also einfach import CommonCrypto verwenden, ohne einen Bridging-Header verwenden zu müssen, wenn die neueste Xcode-Version installiert ist.

Swift 4+

String + Crypto.Swift

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

Daten + 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()
        }
    }
}

Edit: Da der Hash tatsächlich auf den Daten geschieht, spalte ich den Hash-Algorithmus in eine Datenerweiterung auf. Dadurch kann derselbe Algorithmus auch für Hash-Vorgänge beim Pinning von SSL-Zertifikaten verwendet werden.

Hier ist ein kurzes Beispiel, wie Sie es für einen SSL-Pinning-Vorgang verwenden könnten:

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

zurück zur ursprünglichen Antwort

Ich habe die Hash-Algorithmen folgendermaßen getestet:

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

und das sind die gedruckten Ergebnisse:

md5: c2a9ce57e8df081b4baad80d81868bbb
sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223
sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7
sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b
sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450
sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883
16
digitalHound

Swift 4. *, Xcode 10 Update:

In Xcode 10 müssen Sie Bridging-Header Anymore nicht mehr verwenden. Sie können direkt mit importieren 

import CommonCrypto

Und dann schreibe eine Methode wie:

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

Verwendungszweck : 

MD5("This is my string")

Ausgabe:

c2a9ce57e8df081b4baad80d81868bbb
14
Invictus Cody

Nur zwei Anmerkungen hier:

Die Verwendung von Crypto ist zu viel Aufwand, um genau dies zu erreichen.

Die akzeptierte Antwort ist perfekt! Trotzdem wollte ich nur einen Swift _ ​​ier Code-Ansatz mit Swift 2.2 freigeben. 

Bitte beachten Sie, dass Sie in Ihrer Bridging-Header -Datei noch #import <CommonCrypto/CommonCrypto.h> eingeben müssen

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]) }
    }
}
10
Hugo Alonso

Hier ist eine Erweiterung, die auf Zaph-Antworten basiert

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

Vollständig kompatibel mit Swift 3.0. Sie müssen in Ihrer Bridging-Header-Datei noch #import <CommonCrypto/CommonCrypto.h>

6

Swift 5 Antwort als String-Erweiterung (basierend auf der großartigen Antwort von 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])
        }
    }
}

Verwendung:

print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
3
Tamás Sengel

Ab iOS 13 (das erst im September 2019 veröffentlicht wird) hat Apple das Framework CryptoKit hinzugefügt, sodass Sie CommonCrypto nicht mehr importieren oder sich mit der C-API befassen müssen:

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
mluisbrown

Ich habe Karthago und Cyrpto dazu benutzt.

  1. Installiere Carthage, wenn du es noch nicht getan hast

  2. Installiere Crypto in deinem Projekt

  3. 'Cartage Update' ausführen

  4. Wenn Sie von der Kommandozeile aus arbeiten, fügen Sie das Framework in der Swift-Datei hinzu

    #!/usr/bin/env xcrun Swift -F Carthage/Build/Mac
    
  5. Importieren Sie Crypto zu Ihrer Swift-Datei.

  6. dann funktioniert es einfach!

    print( "convert this".MD5 )
    

MD5 ist ein Hash-Algorithmus. Sie müssen dafür nicht die umfangreiche CommonCrypto-Bibliothek verwenden (und von Apple Review abgelehnt werden). Verwenden Sie einfach eine beliebige md5-Hash-Bibliothek.

Eine solche Bibliothek, die ich verwende, ist SwiftHash , eine reine Swift-Implementierung von MD5 (basierend auf http://pajhome.org.uk/crypt/md5/md5.html )

1
Rao

Basierend auf Codys Lösung habe ich die Idee, dass wir klären sollten, was das Ergebnis von MD5 ist, da wir das Ergebnis möglicherweise als Hex-Zeichenfolge oder als Base64-Zeichenfolge verwenden.

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
}

Die obige Funktion gibt tatsächlich einen [UInt8] zurück, und basierend auf diesem Ergebnis können wir eine beliebige Form von Zeichenfolge abrufen, z. B. hex, base64.

Wenn als Endergebnis eine Hex-Zeichenfolge gewünscht wird (wie die Frage fragt), können wir den Rest von Codys Lösung weiterverwenden

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

Wenn eine Base64-Zeichenfolge als Endergebnis gewünscht wird

extension String {
    var md5Base64: String {
        let md5edData = Data(bytes: md5(self))
        return md5edData.base64EncodedString()
    }
}
1
Monsoir

In der Swift-Programmierung ist es besser, eine String-Funktion zu erstellen, damit die Verwendung einfach ist. Hier mache ich eine String-Erweiterung mit einer der oben angegebenen Lösung. Danke @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
}
}

Verwendungszweck

let md5String = "abc".md5()
0
Rahul K Rajan

meine zwei Cent (wenn Sie schnell md5 für Data / NSData benötigen, zum Beispiel haben Sie Binärdateien für Datenträger oder Netzwerke heruntergeladen oder gelesen)

(schamlos aus "Swift 5 Antwort als String-Erweiterung (basierend auf der großartigen Antwort von 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])
        }
    }
} 

prüfung:

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

Eine Antwort für Swift 5 mit korrekter Speicherverwaltung und ohne String Klasse innerhalb der Methode:

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

beispiel

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)

Ergebnisse:

md5 Optional ("671C121427F12FBBA66CEE71C44CB62C")

sha1 Optional ("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")

sha224 Optional ("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")

sha256 Optional ("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")

sha384 Optional ("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")

sha512 Optional (1D595EAFEB2162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86AA68)

0
Vyacheslav

Ich fand diese Bibliothek, die ziemlich gut zu funktionieren scheint.

https://github.com/onmyway133/SwiftHash

MD5("string")
0
Edmund Lee