How can I convert String to MD5 hash in iOS using Swift?

I want to convert a string like "abc" to an MD5 hash. I want to do this in iOS and Swift. I tried using the solutions below, but they do not work for me:

Import CommonCrypto in Swift

How to use CC_MD5 method in fast language.

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

To be more clear, I want to get output in Swift similar to this PHP code output:

$str = "Hello"; echo md5($str); 

Output: 8b1a9953c4611296a827abf8c47804d7

+92
ios swift md5
Aug 23 '15 at 6:28
source share
16 answers

There are two steps:
1. Create md5 data from a string
2. Convert the md5 data to a hexadecimal 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)") 

Exit:

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

Exit:

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

Exit:

md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w ==

Notes:
#import <CommonCrypto/CommonCrypto.h> should be added to the Bridging-Header file

To learn how to create a Bridging-Header, see this SO answer .

In general, MD5 should not be used for new work, SHA256 is the best practice today.

An example from an obsolete section of the documentation:

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

These functions will hash either a string or data input using one of eight cryptographic hashing algorithms.

The name parameter specifies the name of the hash function as a string
Supported functions: MD2, MD4, MD5, SHA1, SHA224, SHA256, SHA384 and SHA512 a In this example, Common Crypto is required
You must have a connecting header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add Security.framework to the project.







This function takes a hash name and a hash string and returns data:

 name: A name of a hash function as a String  
 string: The String to be hashed  
 returns: the hashed result as Data  
 func hash(name:String, string:String) -> Data? { let data = string.data(using:.utf8)! return hash(name:name, data:data) } 

Examples:

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

Exit:

 clearString: clearData0123456 clearData: <636c6561 72446174 61303132 33343536> hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a> hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6> 
+151
Aug 23 '15 at 12:39 on
source share

After reading the other answers here (and the need to support other types of hashes), I wrote a String extension that handles several types of hashes and output types.

NOTE. CommonCrypto is included in Xcode 10, so you can simply import CommonCrypto without having to bind to the bridge header if you have the latest version of Xcode installed ... Otherwise, you need a bridge header.




UPDATE: Both Swift 4 and 5 use the same String + Crypto.swift file below.

There is a separate Data + Crypto.swift file for Swift 5 (see below), because the API for 'withUnsafeMutableBytes' and 'withUnsafeBytes' has changed between Swift 4 and 5.




String + Crypto.swift - (for Swift 4 and 5)

 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 - 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(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 - 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: since the hash really happens with the data, I split the hashing algorithm into data extension. This allows you to use the same algorithm for securing an SSL hash certificate.

Here is a brief example of how you can use it for an SSL pinning operation:

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

back to original answer

I tested the hashing algorithms using this:

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

and these are the printed results:

 md5: c2a9ce57e8df081b4baad80d81868bbb sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223 sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7 sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450 sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883 
+30
Aug 31 '18 at 18:15
source share

SWIFT 3 version 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 } 

Original link from http://iosdeveloperzone.com

+28
Sep 26 '16 at 5:41
source share

Swift 4. *, Xcode 10 Update:

In Xcode 10, you no longer need to use Bridging-Header , you can directly import using

 import CommonCrypto 

And then write a method something like:

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

Using:

 MD5("This is my string") 

Exit:

 c2a9ce57e8df081b4baad80d81868bbb 
+22
Oct. 29 '18 at 11:16
source share

I released a pure Swift implementation that is independent of CommonCrypto or anything else. It is available under the MIT license.

The code consists of one quick file, which you can simply add to your project. If you prefer, you can also use the contained Xcode project with frames and test targets.

It is easy to use:

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

prints: md5: 9e107d9d372bb6826bd81d3542a419d6

The quick file contains documentation and other examples.

+17
Sep 20 '17 at 16:40
source share

Just two notes:

Using Crypto is too much overhead to achieve just that.

The accepted answer is perfect! However, I just wanted to use the Swift ier code using Swift 2.2 .

Please keep in mind that you still need #import <CommonCrypto/CommonCrypto.h> in the Bridging-Header file

 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
May 26 '16 at 23:01
source share

Here's an extension based on zaph's answer

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

Fully compatible with swift 3.0. You should still have #import <CommonCrypto/CommonCrypto.h> in your Bridging Header header file

+6
Aug 24 '17 at 18:35
source share

Starting with iOS 13 (which will be released only in September 2019), Apple has added CryptoKit so you no longer need to import CommonCrypto or work with its C API:

 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() } 
+4
Jun 13 '19 at 11:00
source share

Swift 5's answer as a String extension (based on the excellent Invictus Cody answer ):

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

Using:

 print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/ 
+3
Mar 25 '19 at 21:08
source share

I used Carthage and Sirpto for this.

+1
Jan 29 '16 at 1:08
source share

MD5 is a hashing algorithm, you don’t need to use the cumbersome CommonCrypto library for this (and get rejected from the Apple review), just use any md5 hash library.

One such library that I use is SwiftHash , a clean fast MD5 implementation (based on http://pajhome.org.uk/crypt/md5/md5.html )

+1
Apr 08 '18 at 15:49
source share

In fast programming, it is better to create string functions, so their use will be simple. Here I am doing a String extension using one of the solutions above. Thanks @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 } } 

using

 let md5String = "abc".md5() 
+1
Apr 02 '19 at 7:07
source share

Based on Cody's solution , I have an idea that we should clarify what is the result of MD5, because we can use the result as a hexadecimal string or Base64 string.

 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 } 

The above function actually returns [UInt8] , and based on this result we can get any form of the string, such as hex, base64.

If the end result requires a hexadecimal string (as the question asks), we can continue to use the remainder of the Cody solution

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

If the Base64 string is required as the end result

 extension String { var md5Base64: String { let md5edData = Data(bytes: md5(self)) return md5edData.base64EncodedString() } } 
+1
May 22 '19 at 12:22
source share

I found this library that works very well.

https://github.com/onmyway133/SwiftHash

 MD5("string") 
0
01 Sep '18 at 19:01
source share

my two cents (if you need fast md5 for data / NSData, for example, you downloaded or read a binary for disk or netwkork)

(shamelessly from the "Swift 5 answer as a string extension (based on the excellent Invictus Cody answer")):

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

test:

 print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/ 
0
Apr 04 '19 at 6:19 06:19
source share

The answer is for Swift 5 with proper memory management and no String class inside the method:

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

example

 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) 

Results:

md5 Optional ("671C121427F12FBBA66CEE71C44CB62C")

sha1 Optional ("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")

sha224 Optional ("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")

sha256 Optional ("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")

sha384 Optional ("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")

sha512 Optional ("1D595EAFEB2162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86AA68)

0
Aug 13 '19 at 14:49
source share