Je veux convertir l'entrée d'utilisateur ou supposer n'importe quelle chaîne comme "abc" au hash MD5. Je veux faire cela dans iOS Swift. J'ai référencé les liens ci-dessous mais les solutions ne fonctionnent pas pour moi ou je suis confus de le mettre en œuvre correctement car je suis nouveau dans la programmation Swift. Quelqu'un pourrait-il m'aider avec des étapes claires pour y parvenir? Merci d'avance!
Importation de CommonCrypto dans un cadre Swift
Comment utiliser la méthode CC_MD5 en langage Swift
http://iosdeveloperzone.com/2014/10/03/using-commoncrypto-in-Swift/
Pour être plus clair, je veux y parvenir dans Swift, comme ce que nous faisons en php.
$str = "Hello";
echo md5($str);
Sortie: 8b1a9953c4611296a827abf8c47804d7
Il y a deux étapes:
1. Créer des données md5 à partir d'une chaîne
2. Convertir les données md5 en une chaîne hexagonale
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)")
Sortie:
digérer: 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)")
Sortie:
md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w ==
Remarques:#import <CommonCrypto/CommonCrypto.h>
doit être ajouté à un fichier Bridging-Header
Pour savoir comment créer un en-tête de pontage, voir cette SO réponse .
En général, le MD5 ne doit pas être utilisé pour de nouveaux travaux. SHA256 est une pratique exemplaire actuelle.
MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384, SHA512 (Swift 3+)
Ces fonctions vont hacher l'entrée String ou Data avec l'un des huit algorithmes de hachage cryptographique.
Le paramètre name spécifie le nom de la fonction de hachage sous forme de chaîne.
Les fonctions prises en charge sont MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384 et SHA512 A Cet exemple nécessite Common Crypto
Il est nécessaire d’avoir un en-tête de pontage dans le projet:#import <CommonCrypto/CommonCrypto.h>
Ajoutez le Security.framework au projet.
Cette fonction prend un nom de hachage et une chaîne à hacher et renvoie une donnée:
name: nom d'une fonction de hachage en tant que chaîne string: chaîne à hacher renvoie: le résultat haché en tant que données
func hash(name:String, string:String) -> Data? {
let data = string.data(using:.utf8)!
return hash(name:name, data:data)
}
Exemples:
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)")
Sortie:
clearString: clearData0123456
clearData: <636c6561 72446174 61303132 33343536>
hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>
Swift 3
version de 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
}
Lien original de http://iosdeveloperzone.com
J'ai publié une pure implémentation Swift qui ne dépend pas de CommonCrypto ni de quoi que ce soit d'autre. Il est disponible sous la licence MIT.
Le code consiste en un fichier Swift unique que vous pouvez simplement insérer dans votre projet. Si vous préférez, vous pouvez également utiliser le projet Xcode contenu avec des cibles de test d'infrastructure et de test unitaire.
C'est simple à utiliser:
let input = "The quick brown fox jumps over the lazy dog"
let digest = input.utf8.md5
print("md5: \(digest)")
impressions: md5: 9e107d9d372bb6826bd81d3542a419d6
Le fichier Swift contient de la documentation et d’autres exemples.
Après avoir lu les autres réponses ici (et ayant besoin de prendre en charge d'autres types de hachage), j'ai écrit une extension String qui gère plusieurs types de hachage et types de sortie.
NOTE: CommonCrypto est inclus dans Xcode 10, vous pouvez donc simplement import CommonCrypto
sans devoir jouer avec un en-tête de pontage si la dernière version de Xcode est installée ... Sinon, un en-tête de pontage est nécessaire.
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)
}
Data + 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: puisque le hachage se produit réellement sur les données, j'ai divisé l'algorithme de hachage en une extension de données. Cela permet d'utiliser le même algorithme pour les opérations de hachage de hachage par certificat SSL.
Voici un court exemple d'utilisation de ce programme pour une opération d'épinglage SSL:
// 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
}
retour à la réponse originale
J'ai testé les algorithmes de hachage en utilisant ceci:
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)")
}
et voici les résultats imprimés:
md5: c2a9ce57e8df081b4baad80d81868bbb
sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223
sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7
sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b
sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450
sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883
Swift 4. *, mise à jour Xcode 10:
Dans Xcode 10, vous n'avez pas à utiliser Bridging-Header Anymore, vous pouvez importer directement à l'aide de
import CommonCrypto
Et puis écrivez une méthode quelque chose comme:
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])
}
}
Utilisation:
MD5("This is my string")
Sortie:
c2a9ce57e8df081b4baad80d81868bbb
Juste deux notes ici:
L'utilisation de Crypto est trop onéreuse pour y parvenir.
Le réponse acceptée est parfait! Néanmoins, je voulais simplement partager une approche de code Swift _ ier en utilisant Swift 2.2.
N'oubliez pas que vous devez toujours #import <CommonCrypto/CommonCrypto.h>
dans votre fichier Bridging-Header
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]) }
}
}
Voici une extension basée sur la réponse zaph
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()
}
}
}
Entièrement compatible avec Swift 3.0.vous devez toujours #import <CommonCrypto/CommonCrypto.h>
dans votre fichier Bridging-Header
Swift 5 answer en tant qu'extension de chaîne (basé sur la grande réponse d'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])
}
}
}
Utilisation:
print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
Depuis iOS 13 (qui ne sera disponible qu'en septembre 2019), Apple a ajouté le cadre CryptoKit
, de sorte que vous n'avez plus besoin d'importer CommonCrypto ni de gérer son API C:
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()
}
J'ai utilisé Carthage et Cyrpto pour le faire.
exécuter 'mise à jour de cartage'
Si vous utilisez la ligne de commande, ajoutez-le dans le fichier Swift
#!/usr/bin/env xcrun Swift -F Carthage/Build/Mac
Ajoutez import Crypto à votre fichier Swift.
alors ça marche!
print( "convert this".MD5 )
MD5 est un algorithme de hachage, pas besoin d'utiliser la bibliothèque volumineuse CommonCrypto pour cela (et d'être rejeté par Apple), utilisez simplement n'importe quelle bibliothèque de hachage md5.
Une de ces bibliothèques que j’utilise est SwiftHash , une implémentation Swift pure de MD5 (basé sur http://pajhome.org.uk/crypt/md5/md5.html )
Sur la base de solution de Cody , j'ai une idée selon laquelle nous devrions clarifier le résultat de MD5, car nous pourrions utiliser le résultat sous forme de chaîne hexadécimale, ou de chaîne Base64.
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
}
La fonction ci-dessus renvoie en fait un [UInt8]
et, en fonction de ce résultat, nous pouvons obtenir n’importe quelle forme de chaîne, telle que hex, base64.
Si une chaîne hexagonale est souhaitée comme résultat final (comme le demande la question), nous pouvons continuer à utiliser la partie restante de solution de Cody
extension String {
var md5Hex: String {
let length = Int(CC_MD5_DIGEST_LENGTH)
return (0..<length).reduce("") {
$0 + String(format: "%02x", digest[$1])
}
}
}
Si une chaîne Base64 est recherchée comme résultat final
extension String {
var md5Base64: String {
let md5edData = Data(bytes: md5(self))
return md5edData.base64EncodedString()
}
}
En programmation Swift, il est préférable de créer une fonction de chaîne, de sorte que son utilisation sera facile. Ici, je crée une extension String en utilisant l’une des solutions ci-dessus. Merci @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
}
}
Usage
let md5String = "abc".md5()
mes deux cents (si vous avez rapidement besoin de md5 pour Data / NSData, par exemple, vous avez téléchargé ou lu des fichiers binaires pour un disque ou un réseau)
(sans vergogne de "Swift 5 répond comme une extension de chaîne (basé sur l'excellente réponse d'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])
}
}
}
tester:
print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
Une réponse pour Swift 5 avec une gestion de mémoire appropriée et sans la classe String
à l'intérieur de la méthode:
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
}
}
}
exemple
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)
Résultats:
md5 en option ("671C121427F12FBBA66CEE71C44CB62C")
sha1 Facultatif ("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")
sha224 Facultatif ("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")
sha256 Facultatif ("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")
sha384 En option ("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")
sha512 Facultatif ("1D595EAFEB2162672830885D336F7548D481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82F4BAB8A70C06AFC64C610D3CB1FE8A89C8A8A8A8A8A8A4F08C08A08C08A08C08C08C08C08C08C08C08C08C08A08
J'ai trouvé cette bibliothèque qui semble bien fonctionner.
https://github.com/onmyway133/SwiftHash
MD5("string")