在 Swift 3 中对 ansi 字符串使用 MD5 哈希值
Using MD5 hash value on an ansi string in Swift 3
我有一个小函数,它接受一个字符串和 return 它的 MD5 散列值。问题是,它需要一个 UTF8 字符串,我需要它来计算用 iso-8859-1 (~ansi) 编码的字节数组的哈希值。
如何更改以下代码以接受字节字符数组,然后 return 它的散列值?
static 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
}
棘手的部分是 CC_MD5_Update 调用。谢谢
如果您确定 'string' 仅包含 utf8 字符,请使用 string.utf8 调用 CC_MD5_Update,这样:
CC_MD5_Update(context, string.utf8, CC_LONG(string.lengthOfBytes(using: String.Encoding.utf8)))
swift 中的字符串是 'interesting',这是一篇关于该主题的好读物:https://oleb.net/blog/2016/08/swift-3-strings/
您可以轻松修改您的函数以获取任意字节
数组作为参数。 CC_MD5_Update
映射到 Swift 为
func CC_MD5_Update(_ c: UnsafeMutablePointer<CC_MD5_CTX>!, _ data: UnsafeRawPointer!, _ len: CC_LONG) -> Int32
并且您可以将数组作为 UnsafeRawPointer
参数传递:
func md5(bytes: [UInt8]) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
CC_MD5_Update(&context, bytes, CC_LONG(bytes.count))
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=11=]) }.joined()
}
(我也简化了一点。)
或者,传递一个 Data
参数:
func md5(data: Data) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
data.withUnsafeBytes {
_ = CC_MD5_Update(&context, [=12=], CC_LONG(data.count))
}
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=12=]) }.joined()
}
然后可以用作
let s = "foo"
if let data = s.data(using: .isoLatin1) {
let hash = md5(data: data)
print(hash)
}
更新 Swift 5:
import CommonCrypto
func md5(data: Data) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
data.withUnsafeBytes {
_ = CC_MD5_Update(&context, [=14=].baseAddress, CC_LONG(data.count))
}
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=14=]) }.joined()
}
// requires a bridging header with this:
// #import <CommonCrypto/CommonCrypto.h>
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("") {
[=10=] + String(format: "%02x", digest[])
}
}
我有一个小函数,它接受一个字符串和 return 它的 MD5 散列值。问题是,它需要一个 UTF8 字符串,我需要它来计算用 iso-8859-1 (~ansi) 编码的字节数组的哈希值。
如何更改以下代码以接受字节字符数组,然后 return 它的散列值?
static 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
}
棘手的部分是 CC_MD5_Update 调用。谢谢
如果您确定 'string' 仅包含 utf8 字符,请使用 string.utf8 调用 CC_MD5_Update,这样:
CC_MD5_Update(context, string.utf8, CC_LONG(string.lengthOfBytes(using: String.Encoding.utf8)))
swift 中的字符串是 'interesting',这是一篇关于该主题的好读物:https://oleb.net/blog/2016/08/swift-3-strings/
您可以轻松修改您的函数以获取任意字节
数组作为参数。 CC_MD5_Update
映射到 Swift 为
func CC_MD5_Update(_ c: UnsafeMutablePointer<CC_MD5_CTX>!, _ data: UnsafeRawPointer!, _ len: CC_LONG) -> Int32
并且您可以将数组作为 UnsafeRawPointer
参数传递:
func md5(bytes: [UInt8]) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
CC_MD5_Update(&context, bytes, CC_LONG(bytes.count))
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=11=]) }.joined()
}
(我也简化了一点。)
或者,传递一个 Data
参数:
func md5(data: Data) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
data.withUnsafeBytes {
_ = CC_MD5_Update(&context, [=12=], CC_LONG(data.count))
}
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=12=]) }.joined()
}
然后可以用作
let s = "foo"
if let data = s.data(using: .isoLatin1) {
let hash = md5(data: data)
print(hash)
}
更新 Swift 5:
import CommonCrypto
func md5(data: Data) -> String {
var context = CC_MD5_CTX()
var digest = Array<UInt8>(repeating:0, count:Int(CC_MD5_DIGEST_LENGTH))
CC_MD5_Init(&context)
data.withUnsafeBytes {
_ = CC_MD5_Update(&context, [=14=].baseAddress, CC_LONG(data.count))
}
CC_MD5_Final(&digest, &context)
return digest.map { String(format: "%02hhx", [=14=]) }.joined()
}
// requires a bridging header with this:
// #import <CommonCrypto/CommonCrypto.h>
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("") {
[=10=] + String(format: "%02x", digest[])
}
}