Dans objectif-c, cela ressemble à ceci:
#include <sys/xattr.h>
@implementation NSString (reverse)
-(NSString*)sha1
{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (int)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
@end
J'ai besoin de quelque chose comme ça avec Swift, est-ce possible?
S'il vous plaît, montrez l'exemple de travail.
Votre code Objective-C (en utilisant une catégorie NSString
) peut être traduit directement en Swift (En utilisant une extension String
).
Vous devez d’abord créer un "en-tête de pontage" et ajouter
#import <CommonCrypto/CommonCrypto.h>
Ensuite:
extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
for byte in digest {
output.appendFormat("%02x", byte)
}
return output as String
}
}
println("Hello World".sha1())
Cela peut être écrit légèrement plus court et Swifter comme
extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = map(digest) { String(format: "%02hhx", $0) }
return "".join(hexBytes)
}
}
Mise à jour pour Swift 2:
extension String {
func sha1() -> String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding)!
var digest = [UInt8](count:Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
CC_SHA1(data.bytes, CC_LONG(data.length), &digest)
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")
}
}
Pour renvoyer une chaîne encodée en Base 64 au lieu d'une chaîne encodée en hexadécimal, remplacez
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joinWithSeparator("")
avec
return NSData(bytes: digest, length: digest.count).base64EncodedStringWithOptions([])
Mise à jour pour Swift 3:
extension String {
func sha1() -> String {
let data = self.data(using: String.Encoding.utf8)!
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1($0, CC_LONG(data.count), &digest)
}
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
}
}
Pour renvoyer une chaîne encodée en Base 64 au lieu d'une chaîne encodée en hexadécimal, remplacez
let hexBytes = digest.map { String(format: "%02hhx", $0) }
return hexBytes.joined()
par
return Data(bytes: digest).base64EncodedString()
Pour obtenir le résultat sous la forme NSData
, à condition que vous ayez inclus <CommonCrypto/CommonCrypto.h>
dans votre en-tête de pontage:
extension NSData {
func sha1() -> NSData? {
let len = Int(CC_SHA1_DIGEST_LENGTH)
let digest = UnsafeMutablePointer<UInt8>.alloc(len)
CC_SHA1(bytes, CC_LONG(length), digest)
return NSData(bytesNoCopy: UnsafeMutablePointer<Void>(digest), length: len)
}
}
Utilise également une allocation de pointeur appropriée. Invoquez-le comme ceci:
myString.dataUsingEncoding(NSUTF8StringEncoding)?.sha1()
Si vous avez besoin d'une représentation hexadécimale de NSData
, jetez un œil à mon autre réponse .
Oui, c'est possible, copiez cette classe dans votre projet . https://github.com/idrougge/sha1-Swift
Et ce sera facile comme:
SHA1.hexString(from: "myPhrase" )!
Testé pour Swift 3 et Swift 4.
Nous pouvons extraire la logique de chiffrement de chaîne en utilisant sha1 pour trois étapes:
IMHO c'est beaucoup plus lisible et cette version ne nécessite pas NSData.
extension String {
var sha1: String {
guard let data = data(using: .utf8, allowLossyConversion: false) else {
// Here you can just return empty string or execute fatalError with some description that this specific string can not be converted to data
}
return data.digestSHA1.hexString
}
}
fileprivate extension Data {
var digestSHA1: Data {
var bytes: [UInt8] = Array(repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
withUnsafeBytes {
_ = CC_SHA1($0, CC_LONG(count), &bytes)
}
return Data(bytes: bytes)
}
var hexString: String {
return map { String(format: "%02x", UInt8($0)) }.joined()
}
}
Oui, c'est possible: rendre ce code objective-c accessible depuis Swift
Voir documentation .
J'éviterais de la réécrire dans Swift si vous n'obtenez aucun avantage (comme l'utilisation de fonctionnalités spécifiques à Swift).
De plus, dans un projet sur lequel je travaille, j'ai utilisé un code objective-c similaire au vôtre pour gérer les hachages. Au début, j’ai commencé à l’écrire dans Swift, puis j’ai réalisé qu’il était tout simplement plus facile et meilleur de réutiliser le vieil obj-c.