6

我有以下 Objective-C 函数:

+(NSString *)stringToSha1:(NSString *)str{
    NSMutableData *dataToHash = [[NSMutableData alloc] init];
    [dataToHash appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];

    unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([dataToHash bytes], [dataToHash length], hashBytes);
    NSData *encodedData = [NSData dataWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH];
    [dataToHash release];
    NSString *encodedStr = [NSString stringWithUTF8String:[encodedData bytes]];
    //NSString *encodedStr = [[NSString alloc]  initWithBytes:[encodedData bytes]
    //                                            length:[encodedData length] encoding: NSUTF8StringEncoding];
    NSLog(@"String is %@", encodedStr);

    return encodedStr;

}

我想要做的是采用 NSString 和 SHA1 对其进行编码。那部分似乎正在工作,我认为我失败的地方是如何将 NSData 对象转换回清晰的字符串。如果我使用 UTF8 编码,我会得到空白,如果我说 ASCII,我会得到奇怪的字符。我真正想要的是十六进制字符串,但我不知道如何得到它。这是使用 iPhone 3.0 SDK。

目前,我传入的任何字符串都返回为 NULL。

4

4 回答 4

28

我的 SHA1 函数版本(更简单):

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

和MD5:

- (NSString *)md5:(NSString *)str {
const char *cStr = [str UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, strlen(cStr), result);
NSString *s = [NSString  stringWithFormat:
               @"%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]
               ];

    return s;
}
于 2009-09-29T14:31:49.717 回答
3

简短的回答:打开 gcc 警告(-Wall)。

长答案:

NSMutableData *dataToHash = [[NSMutableData alloc] init];
[dataToHash appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];

已损坏:您尝试在需要 NSData 参数的地方使用 C 字符串。采用

NSMutableData *dataToHash = [str dataUsingEncoding:NSUTF8StringEncoding];

反而。

该方法的其余部分采用 SHA1 缓冲区并尝试将此数据解释为 UTF-8 C 字符串,这可能会崩溃或产生任何意外结果。首先,缓冲区不是 UTF-8 字符串。其次,它不是空终止的。

您想要的是将 SHA1 转换为 base 64 或类似字符串。这是一篇关于如何做到这一点的好帖子。

于 2009-08-30T13:01:58.050 回答
1

这就是我最终得到的结果,下一步是将其转换为 NSString 的类别,而不是辅助类中的静态方法:

+(NSString *)stringToSha1:(NSString *)str{
    const char *s = [str cStringUsingEncoding:NSASCIIStringEncoding];
    NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];

    // This is the destination
    uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0};
    // This one function does an unkeyed SHA1 hash of your hash data
    CC_SHA1(keyData.bytes, keyData.length, digest);

    // Now convert to NSData structure to make it usable again
    NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
    // description converts to hex but puts <> around it and spaces every 4 bytes
    NSString *hash = [out description];
    hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""];
    hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""];
    hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""];

    NSLog(@"Hash is %@ for string %@", hash, str);

    return hash;
}
于 2009-08-31T12:47:25.253 回答
-1

乙二醇,您需要定义 CC_SHA1_DIGEST_LENGTH 常数,可能为 20,因为这是根据http://www.itl.nist.gov/fipspubs/fip180-1.htm上的 NIST 规范的 SHA-1 摘要的长度

于 2012-02-11T05:19:28.157 回答