Пытаюсь написать функцию NSString sha1, но она возвращает ноль - PullRequest
5 голосов
/ 30 августа 2009

У меня есть следующая функция 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 ]

27 голосов
/ 29 сентября 2009

Моя версия функции 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;
}
3 голосов
/ 30 августа 2009

Краткий ответ: включить предупреждения gcc (-Wall).

Длинный ответ:

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

не работает: вы пытаетесь использовать строку C, где ожидается аргумент NSData. Используйте

NSMutableData *dataToHash = [str dataUsingEncoding:NSUTF8StringEncoding];

вместо.

Остальная часть метода берет буфер SHA1 и пытается интерпретировать эти данные как строку C UTF-8, которая может привести к сбою или дать неожиданный результат. Во-первых, буфер не является строкой UTF-8. Во-вторых, оно не завершено нулем.

То, что вы хотите - это преобразовать SHA1 в base 64 или аналогичную строку. Вот хороший пост о том, как это сделать.

1 голос
/ 31 августа 2009

Это то, что я закончил, следующим шагом было бы преобразовать его в категорию 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;
}
0 голосов
/ 11 февраля 2012

гликоль, Вам нужно будет определить вашу константу CC_SHA1_DIGEST_LENGTH, вероятно, равную 20, поскольку это длина дайджеста SHA-1 в соответствии со спецификацией NIST на http://www.itl.nist.gov/fipspubs/fip180-1.htm

...