我该如何在iOS中计算SHA-2(最好是SHA 256或SHA 512)哈希值?

59

安全服务API似乎不允许我直接计算哈希。虽然有不少公共领域和自由许可证版本可用,但如果可能的话,我更愿意使用系统库实现。

数据可通过NSData或普通指针访问。

哈希的加密强度对我很重要。 SHA-256是最小可接受的哈希大小。

6个回答

81

这是我用于SHA1的代码:

#import <CommonCrypto/CommonDigest.h>

+ (NSData *)sha1:(NSData *)data {
    unsigned char hash[CC_SHA1_DIGEST_LENGTH];
    if ( CC_SHA1([data bytes], [data length], hash) ) {
        NSData *sha1 = [NSData dataWithBytes:hash length:CC_SHA1_DIGEST_LENGTH];        
        return sha1;
    }
return nil;
}

CC_SHA1替换为CC_SHA256(或您需要的其他算法),并将CC_SHA1_DIGEST_LENGTH替换为CC_SHA256_DIGEST_LENGTH


这个不起作用...将返回的数据转换为NSString后,我得到了nil。如果我传入数据,则下面的“hashed_string”帖子有效。 - TheJeff
@TheJeff - 这个问题并没有说明要将SHA值作为十六进制字符串返回。将NSData转换为NSString可以作为另一个问题单独提出讨论。 - alex-i
@alex-i,你是对的,NSData返回了,但我提到的字符串转换不起作用 - 你必须使用EgeAkpinar下面提出的方法。我仍然很好奇那是什么以及如何工作,但就像你说的那样,这不是这篇文章的目的。 - TheJeff
这个有 Swift 版本吗? - Jayprakash Dubey

35

这里有一个基于NSString的相似实现

+ (NSString *)hashed_string:(NSString *)input
{
    const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:input.length];
    uint8_t digest[CC_SHA256_DIGEST_LENGTH];

    // This is an iOS5-specific method.
    // It takes in the data, how much data, and then output format, which in this case is an int array.
    CC_SHA256(data.bytes, data.length, digest);

    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];

    // Parse through the CC_SHA256 results (stored inside of digest[]).
    for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
        [output appendFormat:@"%02x", digest[i]];
    }

    return output;
}

(感谢http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1提供的资料)


4
对于 iOS 7 及以上版本,您可以使用以下代码计算数据长度:CC_SHA256(data.bytes, (int)data.length, digest); - RyanG
数据应该是[NSData dataWithBytes:cstr length:strlen(cstr)];使用[input dataUsingEncoding:NSUTF8StringEncoding];会更好。 - mikeytdan

3

这是对我有效的方法

func sha256(securityString : String) -> String {
    let data = securityString.dataUsingEncoding(NSUTF8StringEncoding)!
    var hash = [UInt8](count: Int(CC_SHA256_DIGEST_LENGTH), repeatedValue: 0)
    CC_SHA256(data.bytes, CC_LONG(data.length), &hash)
    let output = NSMutableString(capacity: Int(CC_SHA1_DIGEST_LENGTH))
    for byte in hash {
        output.appendFormat("%02x", byte)
    }
    return output as String
}

0

外部链接可能会随着时间的推移而消失。请在您的答案中包含一个自包含的代码片段。 - bdesham

0

我稍微整理了一下https://dev59.com/6G025IYBdhLWcg3wFxqa#13199111,并将其结构化为一个NSString扩展

@interface NSString (SHA2HEX)

/*
 Get the SHA2 (256 bit) digest as a hex string.
 */
@property (nonatomic, readonly) NSString* sha2hex;
@end

@implementation NSString (SHA2HEX)

- (NSString*)sha2hex
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];

    if (data.length > UINT32_MAX)
        return nil;

    uint8_t digest[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(data.bytes, (CC_LONG)data.length, digest);

    const int hexlen = CC_SHA256_DIGEST_LENGTH * 2;
    NSMutableString *hexstr = [NSMutableString stringWithCapacity:hexlen];

    for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
        [hexstr appendFormat:@"%02x", digest[i]];
    }

    return hexstr;
}

@end

0
+ (NSData *)sha256DataFromData:(NSData *)data {
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256([data bytes], (int)[data length], result);
    return [NSData dataWithBytes:result length:CC_SHA256_DIGEST_LENGTH];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接