我如何从一个NSString
创建 SHA1。
假设 NSString 已设置为:
NSString *message = @"Message";
我可以使用PHP创建一个SHA1散列值,代码为sha($message)
。但是不幸的是,在Objective-C中它不能这样工作。
我如何从一个NSString
创建 SHA1。
假设 NSString 已设置为:
NSString *message = @"Message";
我可以使用PHP创建一个SHA1散列值,代码为sha($message)
。但是不幸的是,在Objective-C中它不能这样工作。
我将以下内容归类到了NSString类中(可在https://github.com/hypercrypt/NSString-Hashes获取):
#import <CommonCrypto/CommonDigest.h>
...
- (NSString *)sha1
{
NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (CC_LONG)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;
}
从 Xcode 10.0 开始,您应该使用 import CommonCrypto
,因为它现在在 Swift 中原生可用!如果您最近迁移到 Xcode 10.0 并且使用旧方法,则可以将此作为更改提示:
Command CompileSwift 失败,退出码为非零
NSMutable*
类的*WithCapacity:
方法,因为可以在开始时分配正确的内存大小。 - hypercrypt- (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的解决方案移植到了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
}
}
NSMutableString
在原帖中保留容量的影响。然而,我怀疑任何人都看不出区别 :)试试这个:
#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];
}
以下是我的解决方案,改编自优秀的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
这是一个简洁且高度优化的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
CC_SHA1
。此外,也可以在这里查看。 - Alex