如何使用Swift将string隐藏到sha1?

在Objective-C中,它看起来像这样:

#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 

我需要用Swift这样的东西,可能吗?

请显示工作示例。

您的Objective-C代码(使用NSString类别)可以直接转换为Swift(使用String扩展)。

首先你必须创build一个“桥接头”并添加

 #import <CommonCrypto/CommonCrypto.h> 

然后:

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

这可以写得稍短,Swifter为

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

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

要返回Base-64编码的string而不是hex编码的string,只需replace即可

  let hexBytes = digest.map { String(format: "%02hhx", $0) } return hexBytes.joinWithSeparator("") 

  return NSData(bytes: digest, length: digest.count).base64EncodedStringWithOptions([]) 

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

要返回Base-64编码的string而不是hex编码的string,只需replace即可

  let hexBytes = digest.map { String(format: "%02hhx", $0) } return hexBytes.joined() 

通过

  return Data(bytes: digest).base64EncodedString() 

为了得到NSData的结果,假设你在桥接头文件中包含<CommonCrypto/CommonCrypto.h>

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

也使用适当的指针分配。 像这样调用它:

 myString.dataUsingEncoding(NSUTF8StringEncoding)?.sha1() 

如果你需要NSData的hex表示看看我的其他答案 。

我们可以使用sha1提取用于encryptionstring的逻辑,分为三个步骤:

  1. 将string转换为数据对象
  2. 使用SHA1函数将数据encryption到数据
  3. 转换数据对象为hexstring

恕我直言,它更可读,这个版本不需要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() } } 

是的,这是可能的: 使快速访问的Objective-C代码

见文件 。

如果你没有得到任何好处(比如使用特定于swift的特性),我会避免在swift中重写它。

另外,在我正在开发的一个项目中,我使用了一些类似于你的Objective-C代码来处理哈希。 一开始我开始写速度很快,然后我意识到重新使用旧的好的obj-c会更容易,更好。