2009-08-30 53 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