如何使用 Swift 将字符串转换为 iOS 中的 MD5 散列?
How can I convert a String to an MD5 hash in iOS using Swift?
我想将 "abc" 之类的字符串转换为 MD5 散列。我想在 iOS 和 Swift 中执行此操作。我已尝试使用以下解决方案,但它们对我不起作用:
Importing CommonCrypto in a Swift framework
How to use CC_MD5 method in swift language.
http://iosdeveloperzone.com/2014/10/03/using-commoncrypto-in-swift/
更清楚地说,我想在 Swift 中实现类似于此 PHP 代码输出的输出:
$str = "Hello";
echo md5($str);
输出:8b1a9953c4611296a827abf8c47804d7
有两个步骤:
1.从字符串
创建md5数据
2.将md5数据转换为十六进制字符串
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)")
输出:
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", [=11=]) }.joined()
print("md5Hex: \(md5Hex)")
let md5Base64 = md5Data.base64EncodedString()
print("md5Base64: \(md5Base64)")
输出:
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", [=12=]) }.joined()
print("md5Hex: \(md5Hex)")
let md5Base64 = md5Data.base64EncodedString()
print("md5Base64: \(md5Base64)")
输出:
md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w==
备注:
#import <CommonCrypto/CommonCrypto.h>
必须添加到 Bridging-Header 文件
有关如何创建桥接头,请参阅 this SO answer。
一般来说,MD5 不应该用于新工作,SHA256 是当前的最佳实践。
已弃用文档部分的示例:
MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384、SHA512 (Swift 3+)
These functions will hash either String or Data input with one of eight cryptographic hash algorithms.
name 参数将哈希函数名称指定为字符串
支持的函数有 MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384 和 SHA512
一种
此示例需要 Common Crypto
必须有项目的桥接头:
#import <CommonCrypto/CommonCrypto.h>
将 Security.framework 添加到项目中。
这个函数需要一个散列名称和要散列的字符串和returns一个数据:
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)
}
示例:
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)")
输出:
clearString: clearData0123456
clearData: <636c6561 72446174 61303132 33343536>
hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>
我用 Carthage 和 Cyrpto 来做这个。
执行'cartage update'
如果您是 运行 从命令行添加到 swift 文件中的框架
#!/usr/bin/env xcrun swift -F Carthage/Build/Mac
将 import Crypto 添加到您的 swift 文件。
那么就可以了!
print( "convert this".MD5 )
Just two notes here:
使用 Crypto 实现这一目标的开销太大。
完美!尽管如此,我只是想分享一个 Swift ier 代码方法,使用 Swift 2.2.
请记住,您仍然需要在 Bridging-Header 文件中 #import <CommonCrypto/CommonCrypto.h>
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("") { [=10=] + String(format: "%02x", digest[]) }
}
}
SWIFT 3
版本 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
}
的原始 link
这是一个基于 zaph 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", [=10=]) }.joined()
}
}
}
完全兼容 swift 3.0.you 仍然需要 #import <CommonCrypto/CommonCrypto.h>
在你的桥接头文件中
我发布了一个不依赖于 CommonCrypto 或其他任何东西的 pure Swift implementation。它在 MIT 许可下可用。
该代码由一个 single swift file 组成,您可以直接将其放入您的项目中。如果您愿意,还可以将包含的 Xcode 项目与框架和单元测试目标一起使用。
使用简单:
let input = "The quick brown fox jumps over the lazy dog"
let digest = input.utf8.md5
print("md5: \(digest)")
打印:md5: 9e107d9d372bb6826bd81d3542a419d6
swift 文件包含文档和更多示例。
MD5 是一种哈希算法,不需要为此使用笨重的 CommonCrypto 库(并被 Apple 审查拒绝),只需使用任何 md5 哈希库即可。
我使用的一个这样的库是 SwiftHash, a pure swift implementation of MD5 (based on http://pajhome.org.uk/crypt/md5/md5.html)
在阅读了此处的其他答案(并且还需要支持其他哈希类型)后,我编写了一个 String 扩展来处理多种哈希类型和输出类型。
注意:CommonCrypto 包含在 Xcode 10 中,因此如果您拥有最新的 Xcode,您可以简单地 import CommonCrypto
而不必弄乱桥接头安装的版本...否则需要桥接头。
更新:Swift 4 和 5 使用下面相同的 String+Crypto.swift 文件。
Swift 5(见下文)有一个单独的 Data+Crypto.swift 文件,因为 'withUnsafeMutableBytes' 和 'withUnsafeBytes' 的 api 在 Swift 4 & 5.
String+Crypto.swift -- (对于 Swift 4 和 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 -- 数据+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", [=11=]) }.joined()
case .base64: return digest.base64EncodedString()
}
}
}
SWIFT 4 -- 数据+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", [=12=]) }.joined()
case .base64: return digest.base64EncodedString()
}
}
}
编辑:因为散列实际上发生在数据上,所以我将散列算法拆分为数据扩展。这也允许将相同的算法用于 SSL 证书固定哈希操作。
这是一个简短的示例,说明如何将其用于 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
}
返回原答案
我用这个测试了哈希算法:
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)")
}
这是打印结果:
md5: c2a9ce57e8df081b4baad80d81868bbb
sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223
sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7
sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b
sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450
sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883
我发现这个库似乎工作得很好。
https://github.com/onmyway133/SwiftHash
MD5("string")
Swift 4.* , Xcode 10 更新:
在Xcode10中你不必再使用Bridging-Header,你可以直接使用
导入
import CommonCrypto
然后写一个类似这样的方法:
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("") {
[=11=] + String(format: "%02x", digest[])
}
}
用法:
MD5("This is my string")
输出:
c2a9ce57e8df081b4baad80d81868bbb
Swift 5 答案作为字符串扩展(基于 ):
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("") {
[=10=] + String(format: "%02x", digest[])
}
}
}
用法:
print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
在swift编程中最好做一个字符串函数,使用起来会方便一些。
在这里,我使用上面给出的解决方案之一进行 String 扩展。谢谢@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
}
}
用法
let md5String = "abc".md5()
我的两分钱(如果你需要快速 md5 用于 Data/NSData,例如你为磁盘或网络下载或读取二进制文件)
(无耻来自"Swift 5 answer as a String extension (based on the great answer of 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("") {
[=10=] + String(format: "%02x", digest[])
}
}
}
测试:
print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
基于,我有一个想法,我们应该弄清楚MD5的结果是什么,因为我们可能会将结果用作十六进制字符串或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
}
上面的函数其实是returns一个[UInt8]
,根据这个结果,我们可以得到任意形式的字符串,比如hex,base64。
如果想要一个十六进制字符串作为最终结果(如问题所问),我们可以继续使用
的其余部分
extension String {
var md5Hex: String {
let length = Int(CC_MD5_DIGEST_LENGTH)
return (0..<length).reduce("") {
[=11=] + String(format: "%02x", digest[])
}
}
}
如果想要一个Base64字符串作为最终结果
extension String {
var md5Base64: String {
let md5edData = Data(bytes: md5(self))
return md5edData.base64EncodedString()
}
}
自 iOS13 Apple 添加了 CryptoKit
框架,因此您不再需要导入 CommonCrypto 或处理其 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", [=10=])
}.joined()
}
Swift 5 的答案,具有适当的内存管理且方法内部没有 String
class:
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
}
}
}
例子
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)
结果:
md5 Optional("671C121427F12FBBA66CEE71C44CB62C")
sha1 Optional("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")
sha224
Optional("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")
sha256
Optional("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")
sha384
Optional("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")
sha512
Optional("1D595EAFEB2162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86AA68")
import CryptoKit
private func MD5Base64(_ string: String) -> String {
let digest = Insecure.MD5.hash(data: string.data(using: .utf8) ?? Data())
let digestString = digest.map { String(format: "%02hhx", [=10=]) }.joined()
return digestString.toBase64()
}
extension String {
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
}
}
在Swift5.3你可以做到
import CryptoKit
func md5Hash(_ source: String) -> String {
return Insecure.MD5.hash(data: source.data(using: .utf8)!).map { String(format: "%02hhx", [=10=]) }.joined()
}
Swift 5.3:基于@Radu Ursache 和@mluisbrown 的回答:String
的简单扩展
import CryptoKit
extension String {
func md5() -> String {
return Insecure.MD5.hash(data: self.data(using: .utf8)!).map { String(format: "%02hhx", [=10=]) }.joined()
}
}
用法:
"My awesome String".md5()
我想将 "abc" 之类的字符串转换为 MD5 散列。我想在 iOS 和 Swift 中执行此操作。我已尝试使用以下解决方案,但它们对我不起作用:
Importing CommonCrypto in a Swift framework
How to use CC_MD5 method in swift language.
http://iosdeveloperzone.com/2014/10/03/using-commoncrypto-in-swift/
更清楚地说,我想在 Swift 中实现类似于此 PHP 代码输出的输出:
$str = "Hello";
echo md5($str);
输出:8b1a9953c4611296a827abf8c47804d7
有两个步骤:
1.从字符串
创建md5数据
2.将md5数据转换为十六进制字符串
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)")
输出:
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", [=11=]) }.joined()
print("md5Hex: \(md5Hex)")
let md5Base64 = md5Data.base64EncodedString()
print("md5Base64: \(md5Base64)")
输出:
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", [=12=]) }.joined()
print("md5Hex: \(md5Hex)")
let md5Base64 = md5Data.base64EncodedString()
print("md5Base64: \(md5Base64)")
输出:
md5Hex: 8b1a9953c4611296a827abf8c47804d7
md5Base64: ixqZU8RhEpaoJ6v4xHgE1w==
备注:
#import <CommonCrypto/CommonCrypto.h>
必须添加到 Bridging-Header 文件
有关如何创建桥接头,请参阅 this SO answer。
一般来说,MD5 不应该用于新工作,SHA256 是当前的最佳实践。
已弃用文档部分的示例:
MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384、SHA512 (Swift 3+)
These functions will hash either String or Data input with one of eight cryptographic hash algorithms.
name 参数将哈希函数名称指定为字符串
支持的函数有 MD2、MD4、MD5、SHA1、SHA224、SHA256、SHA384 和 SHA512
一种
此示例需要 Common Crypto
必须有项目的桥接头:
#import <CommonCrypto/CommonCrypto.h>
将 Security.framework 添加到项目中。
这个函数需要一个散列名称和要散列的字符串和returns一个数据:
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)
}
示例:
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)")
输出:
clearString: clearData0123456
clearData: <636c6561 72446174 61303132 33343536>
hashSHA256: <aabc766b 6b357564 e41f4f91 2d494bcc bfa16924 b574abbd ba9e3e9d a0c8920a>
hashMD5: <4df665f7 b94aea69 695b0e7b baf9e9d6>
我用 Carthage 和 Cyrpto 来做这个。
执行'cartage update'
如果您是 运行 从命令行添加到 swift 文件中的框架
#!/usr/bin/env xcrun swift -F Carthage/Build/Mac
将 import Crypto 添加到您的 swift 文件。
那么就可以了!
print( "convert this".MD5 )
Just two notes here:
使用 Crypto 实现这一目标的开销太大。
请记住,您仍然需要在 Bridging-Header 文件中 #import <CommonCrypto/CommonCrypto.h>
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("") { [=10=] + String(format: "%02x", digest[]) }
}
}
SWIFT 3
版本 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
}
的原始 link
这是一个基于 zaph 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", [=10=]) }.joined()
}
}
}
完全兼容 swift 3.0.you 仍然需要 #import <CommonCrypto/CommonCrypto.h>
在你的桥接头文件中
我发布了一个不依赖于 CommonCrypto 或其他任何东西的 pure Swift implementation。它在 MIT 许可下可用。
该代码由一个 single swift file 组成,您可以直接将其放入您的项目中。如果您愿意,还可以将包含的 Xcode 项目与框架和单元测试目标一起使用。
使用简单:
let input = "The quick brown fox jumps over the lazy dog"
let digest = input.utf8.md5
print("md5: \(digest)")
打印:md5: 9e107d9d372bb6826bd81d3542a419d6
swift 文件包含文档和更多示例。
MD5 是一种哈希算法,不需要为此使用笨重的 CommonCrypto 库(并被 Apple 审查拒绝),只需使用任何 md5 哈希库即可。
我使用的一个这样的库是 SwiftHash, a pure swift implementation of MD5 (based on http://pajhome.org.uk/crypt/md5/md5.html)
在阅读了此处的其他答案(并且还需要支持其他哈希类型)后,我编写了一个 String 扩展来处理多种哈希类型和输出类型。
注意:CommonCrypto 包含在 Xcode 10 中,因此如果您拥有最新的 Xcode,您可以简单地 import CommonCrypto
而不必弄乱桥接头安装的版本...否则需要桥接头。
更新:Swift 4 和 5 使用下面相同的 String+Crypto.swift 文件。
Swift 5(见下文)有一个单独的 Data+Crypto.swift 文件,因为 'withUnsafeMutableBytes' 和 'withUnsafeBytes' 的 api 在 Swift 4 & 5.
String+Crypto.swift -- (对于 Swift 4 和 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 -- 数据+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", [=11=]) }.joined()
case .base64: return digest.base64EncodedString()
}
}
}
SWIFT 4 -- 数据+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", [=12=]) }.joined()
case .base64: return digest.base64EncodedString()
}
}
}
编辑:因为散列实际上发生在数据上,所以我将散列算法拆分为数据扩展。这也允许将相同的算法用于 SSL 证书固定哈希操作。
这是一个简短的示例,说明如何将其用于 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
}
返回原答案
我用这个测试了哈希算法:
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)")
}
这是打印结果:
md5: c2a9ce57e8df081b4baad80d81868bbb
sha1: 37fb219bf98bee51d2fdc3ba6d866c97f06c8223
sha224: f88e2f20aa89fb4dffb6bdc62d7bd75e1ba02574fae4a437c3bf49c7
sha256: 9da6c02379110815278b615f015f0b254fd3d5a691c9d8abf8141655982c046b
sha384: d9d7fc8aefe7f8f0a969b132a59070836397147338e454acc6e65ca616099d03a61fcf9cc8c4d45a2623145ebd398450
sha512: 349cc35836ba85915ace9d7f895b712fe018452bb4b20ff257257e12adeb1e83ad780c6568a12d03f5b2cb1e3da23b8b7ced9012a188ef3855e0a8f3db211883
我发现这个库似乎工作得很好。
https://github.com/onmyway133/SwiftHash
MD5("string")
Swift 4.* , Xcode 10 更新:
在Xcode10中你不必再使用Bridging-Header,你可以直接使用
导入import CommonCrypto
然后写一个类似这样的方法:
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("") {
[=11=] + String(format: "%02x", digest[])
}
}
用法:
MD5("This is my string")
输出:
c2a9ce57e8df081b4baad80d81868bbb
Swift 5 答案作为字符串扩展(基于
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("") {
[=10=] + String(format: "%02x", digest[])
}
}
}
用法:
print("test".md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
在swift编程中最好做一个字符串函数,使用起来会方便一些。 在这里,我使用上面给出的解决方案之一进行 String 扩展。谢谢@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
}
}
用法
let md5String = "abc".md5()
我的两分钱(如果你需要快速 md5 用于 Data/NSData,例如你为磁盘或网络下载或读取二进制文件)
(无耻来自"Swift 5 answer as a String extension (based on the great answer of 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("") {
[=10=] + String(format: "%02x", digest[])
}
}
}
测试:
print("test".data.md5Value) /*098f6bcd4621d373cade4e832627b4f6*/
基于
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
}
上面的函数其实是returns一个[UInt8]
,根据这个结果,我们可以得到任意形式的字符串,比如hex,base64。
如果想要一个十六进制字符串作为最终结果(如问题所问),我们可以继续使用
extension String {
var md5Hex: String {
let length = Int(CC_MD5_DIGEST_LENGTH)
return (0..<length).reduce("") {
[=11=] + String(format: "%02x", digest[])
}
}
}
如果想要一个Base64字符串作为最终结果
extension String {
var md5Base64: String {
let md5edData = Data(bytes: md5(self))
return md5edData.base64EncodedString()
}
}
自 iOS13 Apple 添加了 CryptoKit
框架,因此您不再需要导入 CommonCrypto 或处理其 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", [=10=])
}.joined()
}
Swift 5 的答案,具有适当的内存管理且方法内部没有 String
class:
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
}
}
}
例子
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)
结果:
md5 Optional("671C121427F12FBBA66CEE71C44CB62C")
sha1 Optional("A6A40B223AE634CFC8C191DDE024BF0ACA56D7FA")
sha224 Optional("334370E82F2F5ECF5B2CA0910C6176D94CBA12FD6F518A7AB8D12ADE")
sha256 Optional("8CF5ED971D6EE2579B1BDEFD4921415AC03DA45B49B89665B3DF197287EFC89D")
sha384 Optional("04BB3551CBD60035BA7E0BAA141AEACE1EF5E17317A8FD108DA12A7A8E98C245E14F92CC1A241C732209EAC9D600602E")
sha512 Optional("1D595EAFEB2162672830885D336F75FD481548AC463BE16A8D98DB33637213F1AEB36FA4977B9C23A82A4FAB8A70C06AFC64C610D3CB1FE77A609DC8EE86AA68")
import CryptoKit
private func MD5Base64(_ string: String) -> String {
let digest = Insecure.MD5.hash(data: string.data(using: .utf8) ?? Data())
let digestString = digest.map { String(format: "%02hhx", [=10=]) }.joined()
return digestString.toBase64()
}
extension String {
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
}
}
在Swift5.3你可以做到
import CryptoKit
func md5Hash(_ source: String) -> String {
return Insecure.MD5.hash(data: source.data(using: .utf8)!).map { String(format: "%02hhx", [=10=]) }.joined()
}
Swift 5.3:基于@Radu Ursache 和@mluisbrown 的回答:String
的简单扩展import CryptoKit
extension String {
func md5() -> String {
return Insecure.MD5.hash(data: self.data(using: .utf8)!).map { String(format: "%02hhx", [=10=]) }.joined()
}
}
用法:
"My awesome String".md5()