2009-08-30 57 views
5

我有以下的Objective-C的功能:想写的NSString SHA1功能,但它返回null

+(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。

+0

单独问题:这更好地实现为NSString类别而不是类方法。该方法将是 - (NSString *)sha1String。如果你发现你想保留它的类方法,它应该有一个名称,如+(NSString *)sha1StringForString:(NSString *)字符串。 “sha1”(这是一个二进制表示)和sha1String之间的混淆正是你首先遇到麻烦的原因。适当的命名将有助于防止相同类型的后期混淆。 – 2009-08-30 13:53:18

回答

3

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

龙答:

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

被打破:您尝试使用C字符串,其中一个NSData参数的预期。使用

NSMutableData *dataToHash = [str dataUsingEncoding:NSUTF8StringEncoding]; 

代替。

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

你想要的是将SHA1转换为基础64或类似的字符串。 Here's a nice post关于如何做到这一点。

+0

谢谢,我是这个C业务的大部分新手,但看起来很容易 – rustyshelf 2009-08-31 02:35:03

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; 
} 
+1

这只能为纯ASCII字符串创建哈希。 – 2009-09-01 17:26:51

+0

感谢您的提示,但这就是我需要的。 – rustyshelf 2009-09-02 03:07:30

26

我的版本SHA1功能(simplier ):

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

您不需要调用lowercaseString。只需将“02X”更改为“02x”即可。 – Seunghoon 2012-01-11 06:50:47

+0

完美! thanx很多 – virata 2012-05-02 06:14:52