从NSString创buildSHA1哈希

我如何从NSString创build一个SHA1。

比方说NSString被设置为:

 NSString *message = @"Message"; 

我可以使用PHP来创buildsha($message)的SHA1哈希。 但不幸的是,它不能像Objective-C那样工作。

我有这个在NSString的类别(可在https://github.com/hypercrypt/NSString-哈希; ):

 #import <CommonCrypto/CommonDigest.h> ... - (NSString *)sha1 { NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; uint8_t digest[CC_SHA1_DIGEST_LENGTH]; CC_SHA1(data.bytes, 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; } 

我很喜欢hypercrypt的答案,但是我被鼓励发表我的评论。

你可以看看CC_SHA1 ,或者这个相关的SO问题。

 - (NSString *)sha1:(NSString *)str { const char *cStr = [str UTF8String]; unsigned char result[CC_SHA1_DIGEST_LENGTH]; CC_SHA1(cStr, strlen(cStr), result); NSString *s = [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15], result[16], result[17], result[18], result[19] ]; return s; } 

我非常喜欢hypercrypt的答案,我把它打包成一个小的git回购。 查看Github上的NSString类别。

也可以随意添加任何其他好的NSString Crypto

尝试这个:

 #import <CommonCrypto/CommonDigest.h> -(NSData *) selector { unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH]; CC_SHA1([dataToHash bytes], [dataToHash length], hashBytes); NSData *data = [[NSData alloc] initWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH]; } 

我花了一段时间才将@hypercrypt解决scheme移植到Swift中,所以我决定将其与可能存在相同问题的其他人分享。

一个重要的事情要注意的是,你需要CommonCrypto库,但该库没有Swift模块。 最简单的解决方法是将其导入桥接头中:

 #import <CommonCrypto/CommonCrypto.h> 

一旦导入那里,你不需要别的东西。 只要使用string扩展提供:

 extension String { func sha1() -> String { var selfAsSha1 = "" if 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) for index in 0..<CC_SHA1_DIGEST_LENGTH { selfAsSha1 += String(format: "%02x", digest[Int(index)]) } } return selfAsSha1 } } 

请注意,我的解决scheme不会保留原来的post中的NSMutableString容量。 但是,我怀疑有人会看到区别:)

这是一个简洁和高度优化的NSString类别 :

 @implementation NSString (PMUtils) - (NSString *)sha1Hash { NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; NSData *hash = [data sha1Hash]; return [hash hexString]; } @end @implementation NSData (PMUtils) - (NSString *) hexString { NSUInteger bytesCount = self.length; if (bytesCount) { static char const *kHexChars = "0123456789ABCDEF"; const unsigned char *dataBuffer = self.bytes; char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1)); char *s = chars; for (unsigned i = 0; i < bytesCount; ++i) { *s++ = kHexChars[((*dataBuffer & 0xF0) >> 4)]; *s++ = kHexChars[(*dataBuffer & 0x0F)]; dataBuffer++; } *s = '\0'; NSString *hexString = [NSString stringWithUTF8String:chars]; free(chars); return hexString; } return @""; } - (NSData *)sha1Hash { unsigned char digest[CC_SHA1_DIGEST_LENGTH]; if (CC_SHA1(self.bytes, (CC_LONG)self.length, digest)) { return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; } return nil; } @end 

我在这篇文章中看到了几个不同的可能的改进。

  1. 永远不要做一个没有前缀的类别。 如果你在你的库中实现了[NSString sha1Hash],而在同一个应用中的另一个库实现了相同的方法,但语义略有不同呢? 哪一个是随机的,导致难以诊断的错误。
  2. 如果你想要一个string,现在在标准库里有base64编码。 比手动构buildhexstring更less的工作。

这是我的解决scheme, 从优秀的SocketRocket库的SRHash.m改编而来 :

 // NSString+Sha1Digest.h #import <Foundation/Foundation.h> @interface NSString (LBDigest) - (NSString *)lb_digestString; @end @interface NSData (LBDigest) - (NSString *)lb_digestString; @end // NSString+SHA1Digest.m #import "NSString+Sha1Digest.h" #import <CommonCrypto/CommonDigest.h> static NSData *LBSHA1HashFromBytes(const char *bytes, size_t length) { uint8_t outputLength = CC_SHA1_DIGEST_LENGTH; unsigned char output[outputLength]; CC_SHA1(bytes, (CC_LONG)length, output); return [NSData dataWithBytes:output length:outputLength]; } static NSData *LBSHA1HashFromString(NSString *string) { size_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; return LBSHA1HashFromBytes(string.UTF8String, length); } @implementation NSData (LBDigest) - (NSString *)lb_digestString; { return [LBSHA1HashFromBytes(self.bytes, self.length) base64EncodedStringWithOptions:0]; } @end @implementation NSString (LBDigest) - (NSString *)lb_digestString; { return [LBSHA1HashFromString(self) base64EncodedStringWithOptions:0]; } @end