Swift kullanarak iOS'ta bir Dizeyi MD5 karmasına nasıl dönüştürebilirim?


111

"Abc" gibi bir dizeyi MD5 karmasına dönüştürmek istiyorum. Bunu iOS ve Swift'de yapmak istiyorum. Aşağıdaki çözümleri kullanmayı denedim ama benim için çalışmıyorlardı:

CommonCrypto'yu Swift çerçevesinde içe aktarma

CC_MD5 yöntemi hızlı bir dilde nasıl kullanılır.

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

Daha açık olmak gerekirse, Swift'de bu PHP kodunun çıktısına benzer bir çıktı elde etmek istiyorum:

$str = "Hello";

echo md5($str);

Çıkış: 8b1a9953c4611296a827abf8c47804d7


5
Verdiğiniz bağlantıların nesi var?
jtbandes

2
Verdiğiniz bağlantılar çalışmalıdır. Sorunun tam olarak ne olduğunu açıklayabilir misin? İstediğinizi yapmak için üçüncü taraf bir kitaplık da ekleyebilirsiniz, yani. github.com/krzyzanowskim/CryptoSwift
Eric Amorde

1
Hızlı programlama konusunda yeni olduğumdan bahsettiğim gibi, doğru şekilde uygulamak konusunda kafam karıştı. bu dosyayı (#import <CommonCrypto / CommonCrypto.h>) hızlı denetleyici dosyasına ekliyordum. Ancak cevaplarınız için teşekkürler, aşağıda verilen Bay zaph cevabı ile çözüldü.
user3606682

Yanıtlar:


178

İki adım vardır:
1. Bir dizeden md5 verileri oluşturun
2. md5 verilerini bir onaltılık dizeye dönüştürün

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

Çıktı:

özet: 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)")

Çıktı:

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

Çıktı:

md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w ==

Notlar:
#import <CommonCrypto/CommonCrypto.h>bir Bridging-Header dosyasına eklenmelidir

Bir Bridging-Header'ın nasıl oluşturulacağını öğrenmek için bu SO cevabına bakın .

Genel olarak MD5 yeni işler için kullanılmamalıdır, SHA256 güncel bir en iyi uygulamadır.

Kullanımdan kaldırılmış dokümantasyon bölümünden örnek:

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

Bu işlevler, sekiz kriptografik karma algoritmadan biriyle Dize veya Veri girişine hash uygular.

Name parametresi hash fonksiyon adını String olarak belirtir
Desteklenen fonksiyonlar MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384 ve SHA512 a Bu örnek Common Crypto gerektirir
Projeye bir köprüleme başlığına sahip olmak gereklidir:
#import <CommonCrypto/CommonCrypto.h>
Güvenlik Ekle .framework projeye.



Bu işlev, hash uygulanacak bir hash adı ve String alır ve bir Data döndürür:

name: Dize olarak bir hash işlevinin adı  
string: Hashing uygulanacak dizge  
döndürür: Veri olarak hashing uygulanmış sonuç  
func hash(name:String, string:String) -> Data? {
    let data = string.data(using:.utf8)!
    return hash(name:name, data:data)
}

Örnekler:

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

Çıktı:

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

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

3
Teşekkürler çok @zaph, 2 günden fazla süredir bunun için mücadele ediyorum. Yukarıdaki cevabınızla çözüldü :) Ve evet, MD5'in kullanıldığı web'den eski verileri alıyorum, bu yüzden MD5 kullanmaya zorlanıyorum.
SHA256'yı

String(data: digestData, encoding: String.Encoding.utf8)atarfatal error: unexpectedly found nil while unwrapping an Optional value
Siddharth

@Siddharth Yorumda yeterli bilgi yok, ne digestDataolduğu belli değil . Karma
veriyse

1
Bunu nasıl iyileştirebileceğiniz aşağıda açıklanmıştır: CommonCrypto'nun tamamını değil, yalnızca gerekli sembolleri içe aktarın, çünkü aksi takdirde biraz ek yük olabilir: import var CommonCrypto.CC_MD5_DIGEST_LENGTH import func CommonCrypto.CC_MD5 import typealias CommonCrypto.CC_LONG
Igor Vasilev,

2
@zaph, aşağıdaki cevabımda detaylandırdığım cevabınıza iOS 13 CryptoKit çözümünü eklemek isteyebilirsiniz: stackoverflow.com/a/56578995/368085
mluisbrown

40

Buradaki diğer yanıtları okuduktan sonra (ve diğer hash türlerini de desteklemeye ihtiyaç duyduktan sonra), birden çok hash türünü ve çıktı türünü işleyen bir String uzantısı yazdım.

NOT: CommonCrypto, Xcode 10'a dahildir, böylece import CommonCryptoen son Xcode sürümüne sahipseniz, köprüleme başlığıyla uğraşmanıza gerek kalmadan yapabilirsiniz ... Aksi takdirde bir köprüleme başlığı gereklidir.


GÜNCELLEME: Swift 4 ve 5, aşağıdaki aynı String + Crypto.swift dosyasını kullanır.

Swift 4 ve 5 arasında değişen 'withUnsafeMutableBytes' ve 'withUnsafeBytes' için api olarak Swift 5 için ayrı bir Data + Crypto.swift dosyası var (aşağıya bakın).


String + Crypto.swift - (Swift 4 ve 5 için)

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

SWIFT 5 - Veri + 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()
        }
    }
}

SWIFT 4 - Veri + 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()
        }
    }
}

Düzenleme: Karma aslında Veriler üzerinde gerçekleştiğinden, karma algoritmasını Veri uzantısına böldüm. Bu, aynı algoritmanın SSL Sertifikası sabitleme hash işlemleri için de kullanılmasına izin verir.

Bunu bir SSL Pinning işlemi için nasıl kullanabileceğinize dair kısa bir örnek:

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

orijinal cevaba dön

Hash algoritmalarını şunu kullanarak test ettim:

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

ve bu basılı sonuçlardır:

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

40

Apple, iOS 13 itibariyle CryptoKitçerçeveyi ekledi, böylece artık CommonCrypto'yu içe aktarmanıza veya C API'siyle uğraşmanıza gerek kalmayacak:

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
Ayrıca, MD5'in artık güvensiz olduğu uyarısından kaçınmanın bir yolu olduğunu da belirtmek gerekir. Uyarıyı devre dışı bırakmak için pragmalar için desteğiniz olması için Objective-C'de CommonCrypto uygulamanıza gerek yoktur. Uyarılarla başa çıkmaya önem veren bir ortamda çalışıyorsanız kullanışlı.
marcus.ramsden

28

SWIFT 3sürümü 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 adresinden orijinal bağlantı


23

Swift 4. *, Xcode 10 Güncellemesi:

Xcode 10'da Artık Bridging-Header kullanmak zorunda değilsiniz, kullanarak doğrudan içe aktarabilirsiniz.

import CommonCrypto

Ve sonra şöyle bir yöntem yazın:

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

Kullanım:

MD5("This is my string")

Çıktı:

c2a9ce57e8df081b4baad80d81868bbb

çözümünüz mükemmel bir şekilde çalıştı. Bu MD5 şifreleme ile SALT değeri ekleyebilir miyiz? Dize şifreleme yaparken eklemek istiyorum. tam kullanım bağlantısı sağlayabilir misiniz?
Punita

Neyi başarmaya çalıştığından emin değilim. Tuzlama ile özel şifreleme istiyorsanız "AES128" kullanın. Güvenlik endişenizse, şuna göz atın: stackoverflow.com/a/15775071/3118377 .
Invictus Cody

Teşekkürler Invictus Cody, SALT'ı String ile birleştirdim ve MD5 elde ettim.
Punita

Harika çalışıyor. Ama onu String'e nasıl geri dönüştürürsünüz?
DocAsh59

1
Swift 5: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: .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]) } }
Jim B

17

CommonCrypto ya da başka herhangi bir şeye bağlı olmayan saf bir Swift uygulaması yayınladım . MIT lisansı altında mevcuttur.

Kod, projenize bırakabileceğiniz tek bir hızlı dosyadan oluşur . İsterseniz, içerilen Xcode projesini çerçeve ve birim test hedefleri ile de kullanabilirsiniz.

Kullanımı basit:

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

baskılar: md5: 9e107d9d372bb6826bd81d3542a419d6

Swift dosyası dokümantasyon ve daha fazla örnek içerir.


4
Burada veya Github ReadMe'de belirtilmeyen Swift 4 gerektirir. Common Crypto ile karşılaştırıldığında performans rakamları sağlanmadan kullanım düşünülmemelidir. Not: Common Crypto FIPS 140 sertifikalıdır, SwiftDigest sertifikalıdır. İşte anahtar soru: Bu, uygulama için Common Crypto'dan nasıl daha iyi? Daha güvenli: Hayır, daha hızlı: Hayır.
zaph

1
@zaph Temel amaç, CommonCrypto'ya bağlı olmayan bir md5 uygulamasına sahip olmaktır. Bu, Swift çerçeve hedefleri veya Apple dışı platformlar gibi CommonCrypto'nun mevcut olmadığı durumlarda faydalıdır.
Nikolai Ruhe

4
@zaph Güvenlikle ilgili uygulamaların hafife alınmaması gerektiğini kabul ediyorum. Ancak MD5'in güvenlikten başka kullanımları vardır - veya daha doğrusu güvenlik, MD5'in en kötü performans gösterdiği yerdir. Karma algoritmalar tanımlama, sıralama, depolama, sözlükler, hata tespiti ve diğer nedenlerle kullanılır. MD5, her yerde bulunmasından dolayı özellikle kullanışlıdır. Bu yüzden, birkaç yorumunuza katılıyorum, ancak özüne katılmıyorum. Bence bakış açınız ve tartışmanız çok dar; konunun tamamını kapsamıyor.
Nikolai Ruhe

2
Ayrıca, yeni test ettim ve büyük mesajlar için uygulamam CommonCrypto'dan daha hızlı :)
Nikolai Ruhe

2
Bu uygulamayı beğendim. Çok teşekkürler @NikolaiRuhe! Swift 3 uyumluluğuna kolayca dönüştürebildim. Ayrıca, bir URL verilen dosya içeriğinin hesaplama özetini ve base64 kodlamasını (diğer şeylerin yanı sıra Content-MD5 için yararlı) almayı içeren birkaç kolaylık yöntemi ekledim. @Siddharth, ihtiyacınız olan tek dosya MD5Digest.swift.
biomiker

10

Burada sadece iki not:

Kripto kullanmak , tam da bunu başarmak için çok fazladır.

Kabul edilen cevap mükemmel! Yine de Swift 2.2'yi kullanarak bir Swift ier kod yaklaşımını paylaşmak istedim .

Hala zorunda olduğunu unutmayınız #import <CommonCrypto/CommonCrypto.h>sizin de Köprü-Üst Bilgi dosyası

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

7

Bir String uzantısı olarak Swift 5 yanıtı (Invictus Cody'nin harika cevabına göre ):

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

Kullanım:

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

6

İşte zaph cevabına dayalı bir uzantı

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 ile tam uyumlu. Yine de #import <CommonCrypto/CommonCrypto.h>Bridging-Header dosyanıza ihtiyacınız var


3

Hızlı programlamada bir dizge işlevi yapmak daha iyidir, bu nedenle kullanımı kolay olacaktır. Burada yukarıda verilen çözümlerden birini kullanarak bir String uzantısı yapıyorum. Teşekkürler @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
}
}

Kullanım

let md5String = "abc".md5()

1

Bunu yapmak için Kartaca ve Cyrpto kullandım.

  1. Henüz yapmadıysanız Kartaca'yı yükleyin

  2. Projenize Crypto yükleyin

  3. "kartaj güncellemesi" ni çalıştır

  4. Komut satırından çalıştırıyorsanız, swift dosyasındaki çerçeveyi ekleyin

    #!/usr/bin/env xcrun swift -F Carthage/Build/Mac
  5. Swift dosyanıza ithal Kripto ekleyin.

  6. o zaman sadece çalışır!

    print( "convert this".MD5 )

Yalnızca bir işlev gerektiğinde tam teşekküllü bir kriptografi kitaplığı kullanmak biraz
Mark Bourke

Eski iş parçacığı yorum için özür dile ... Belki, ancak ortak kitaplıklar (muhtemelen) platform değişiklikleriyle her zaman günceldir, böylece ortak sonuçlar verir ve parçalanmayı en aza indirir ve hiç kimse sürekli olarak tekerlekleri yeniden icat etmek veya bir sürü internet kullanmak zorunda kalmaz. güvenilir, hızlı veya standartlara göre biçimlendirilmiş olabilecek veya olmayabilecek kod bulundu. Ben bağımlılıkları en aza indirmekten yanayım, ancak bunun gibi bir durumda, önce işletim sistemi seçeneklerine, ikinci olarak ortak dil seçeneklerine ve ardından üçüncü taraf standart seçeneklerine bakıyorum ve tek seferlik veya "bu adamın kitaplığı oldukça iyi" sonucunu veriyorum. seçenekler son. * omuz silkme *
ChrisH


1

Cody'nin çözümüne dayanarak, MD5'in sonucunun ne olduğunu açıklığa kavuşturmamız gerektiğine dair bir fikrim var, çünkü sonucu bir onaltılık dizi veya bir Base64 dizisi olarak kullanabiliriz.

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
}

Yukarıdaki işlev aslında a döndürür [UInt8]ve bu sonuca göre hex, base64 gibi herhangi bir dizge formunu elde edebiliriz.

Nihai sonuç olarak bir onaltılık dizge istenirse (sorunun sorduğu gibi), Cody'nin çözümünün geri kalan kısmını kullanmaya devam edebiliriz

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

Nihai sonuç olarak bir Base64 dizesi istenirse

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

1

Swift 5 için uygun bellek yönetimi ile ve Stringyöntem içinde sınıf olmadan bir cevap :

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

misal

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)

Sonuçlar:

md5 İsteğe bağlı ("671C121427F12FBBA66CEE71C44CB62C")

sha1 İsteğe bağlı ("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")

sha224 İsteğe bağlı ("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")

sha256 İsteğe bağlı ("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")

sha384 İsteğe bağlı ("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")

sha512 İsteğe bağlı ("1D595EAFEB2162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86AAA609DC8EE86AAA



0

benim iki sentim ( Data / NSData için hızlı bir şekilde md5'e ihtiyacınız varsa , örneğin disk veya netwkork için ikili dosya indirdiyseniz veya okudunuzsa)

("Swift 5 yanıtı bir String uzantısı olarak utanmaz (Invictus Cody'nin harika cevabına göre"):

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

Ölçek:

print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.