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
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.
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>
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
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.
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
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
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]) }
}
}
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>
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*/
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()
}
Ich habe Karthago und Cyrpto dazu benutzt.
'Cartage Update' ausführen
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
Importieren Sie Crypto zu Ihrer Swift-Datei.
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 )
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()
}
}
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()
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*/
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)
Ich fand diese Bibliothek, die ziemlich gut zu funktionieren scheint.
https://github.com/onmyway133/SwiftHash
MD5("string")