Swift 3 делает функции sha1, sha256 и md5
В Swift 2 я использовал следующий код для расширения строковых переменных и для создания sha1, sha256 и md5.
После перехода на быстрый 3 код уже не работает! Я попытался преобразовать его, но столкнулся с непрерывными ошибками.
Любая идея, как я могу это решить?
extension NSData {
func hexString() -> String {
var string = String()
for i in UnsafeBufferPointer<UInt8>(start: UnsafeMutablePointer<UInt8>(bytes), count: length) {
string += Int(i).hexString()
}
return string
}
func MD5() -> NSData {
let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))!
CC_MD5(bytes, CC_LONG(length), UnsafeMutablePointer<UInt8>(result.mutableBytes))
return NSData(data: result)
}
func SHA1() -> NSData {
let result = NSMutableData(length: Int(CC_SHA1_DIGEST_LENGTH))!
CC_SHA1(bytes, CC_LONG(length), UnsafeMutablePointer<UInt8>(result.mutableBytes))
return NSData(data: result)
}
func SHA256() -> NSData {
let result = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH))
CC_SHA256(bytes, CC_LONG(length), UnsafeMutablePointer(result!.mutableBytes))
return NSData(data: result!)
}
}
extension String {
func hexString() -> String {
return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.hexString()
}
func MD5() -> String {
return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.MD5().hexString()
}
func SHA1() -> String {
return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.SHA1().hexString()
}
func SHA256() -> String {
return (self as NSString).dataUsingEncoding(NSUTF8StringEncoding)!.SHA256().hexString()
}
}
Ответы
Ответ 1
Лучше использовать Swift Data
в Swift 3.
Data
И при работе с Data
вам нужно использовать withUnsafeBytes(_:)
или withUnsafeMutableBytes(_:)
, где вы использовали bytes
или mutableBytes
соответственно.
withUnsafeBytes (_:)
withUnsafeMutableBytes (_:)
extension Data {
func hexString() -> String {
let string = self.map{Int($0).hexString()}.joined()
return string
}
func MD5() -> Data {
var result = Data(count: Int(CC_MD5_DIGEST_LENGTH))
_ = result.withUnsafeMutableBytes {resultPtr in
self.withUnsafeBytes {(bytes: UnsafePointer<UInt8>) in
CC_MD5(bytes, CC_LONG(count), resultPtr)
}
}
return result
}
/*
... nearly the same for `SHA1` and `SHA256`.
*/
}
extension String {
func hexString() -> String {
return self.data(using: .utf8)!.hexString()
}
func MD5() -> String {
return self.data(using: .utf8)!.MD5().hexString()
}
/*
... nearly the same for `SHA1` and `SHA256`.
*/
}
Я предпочитаю делать вычисляемые свойства, чем методы без аргументов (для относительно легких задач). Вам нужно исправить все части, используя их, но вы можете написать что-то вроде этого:
extension Int {
var hexString: String {
return ...
}
}
extension Data {
var hexString: String {
let string = self.map{Int($0).hexString}.joined()
return string
}
var MD5: Data {
var result = Data(count: Int(CC_MD5_DIGEST_LENGTH))
_ = result.withUnsafeMutableBytes {resultPtr in
self.withUnsafeBytes {(bytes: UnsafePointer<UInt8>) in
CC_MD5(bytes, CC_LONG(count), resultPtr)
}
}
return result
}
/*
... nearly the same for `SHA1` and `SHA256`.
*/
}
extension String {
var hexString: String {
return self.data(using: .utf8)!.hexString
}
var MD5: String {
return self.data(using: .utf8)!.MD5.hexString
}
/*
... nearly the same for `SHA1` and `SHA256`.
*/
}
Может быть более быстрое исправление для вашего кода с помощью NSData
, но я рекомендую вам перейти на Data
в Swift 3.
Ответ 2
func MD5() -> String {
let length = Int(CC_MD5_DIGEST_LENGTH)
var digest = [UInt8](repeating: 0, count: length)
if let d = self.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])
}
}
Ответ 3
Я нахожу большую часть ответа в порядке, но если у нас должно быть истинное универсальное решение, я думаю, что нам нужно повысить его уровень.
CC_LONG
- это просто UInt32
и не будет поддерживать действительно большие структуры данных.
Это мое решение в Swift 3:
Сначала мы создаем основу, которая работает с Data
:
struct Sha256 {
let context = UnsafeMutablePointer<CC_SHA256_CTX>.allocate(capacity:1)
init() {
CC_SHA256_Init(context)
}
func update(data: Data) {
data.withUnsafeBytes { (bytes: UnsafePointer<Int8>) -> Void in
let end = bytes.advanced(by: data.count)
for f in sequence(first: bytes, next: { $0.advanced(by: Int(CC_LONG.max)) }).prefix(while: { (current) -> Bool in current < end}) {
_ = CC_SHA256_Update(context, f, CC_LONG(Swift.min(f.distance(to: end), Int(CC_LONG.max))))
}
}
}
func final() -> Data {
var digest = [UInt8](repeating: 0, count:Int(CC_SHA256_DIGEST_LENGTH))
CC_SHA256_Final(&digest, context)
return Data(bytes: digest)
}
}
Для удобства мы делаем расширение для Data:
extension Data {
func sha256() -> Data {
let s = Sha256()
s.update(data: self)
return s.final()
}
}
И последнее расширение для String:
extension String {
func sha256() -> Data {
return self.data(using: .utf8)!.sha256()
}
}
При необходимости преобразуйте результат из Data
в шестнадцатеричную строку или что-то еще в зависимости от вашего варианта использования.
Это решение может использоваться для Sha512, MD5 и т.д., чтобы получить настоящие универсальные решения с Apple CommonCrypto, которые легко распространяться на множество различных случаев использования.
Ответ 4
Для завершения кратчайшее и наиболее гибкое решение в Swift 4:
extension Data {
var hexString: String {
return map { String(format: "%02hhx", $0) }.joined()
}
var md5: Data {
var digest = [Byte](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
self.withUnsafeBytes({
_ = CC_MD5($0, CC_LONG(self.count), &digest)
})
return Data(bytes: digest)
}
var sha1: Data {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
self.withUnsafeBytes({
_ = CC_SHA1($0, CC_LONG(self.count), &digest)
})
return Data(bytes: digest)
}
var sha256: Data {
var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
self.withUnsafeBytes({
_ = CC_SHA256($0, CC_LONG(self.count), &digest)
})
return Data(bytes: digest)
}
}
extension String {
var md5: Data {
return self.data(using: .utf8)!.md5
}
var sha1: Data {
return self.data(using: .utf8)!.sha1
}
var sha256: Data {
return self.data(using: .utf8)!.sha256
}
}
Ответ 5
Создание SHA-256 легко с этой функцией на AfriwanLib:
sha256(value: "value to convert")
это учебная ссылка: https://diponten.com/2019/07/10/sha/