CC_SHA1哈希密码和隐式转换损失在iOS



我正在尝试散列密码并遵循教程。我有#define kSalt @"adlfu3489tyh2jnkLIUGI&%EV(&0982cbgrykxjnk8855"添加到我的密码,我像这样散列:

    NSString *saltedPassword = [NSString stringWithFormat:@"%@%@", self.passwordField.text, kSalt];
    NSString *hashedPassword = nil;
    unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
    NSData *data = [saltedPassword dataUsingEncoding:NSUTF8StringEncoding];
    if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
        hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
    }
    else{
        NSLog(@"Error");
    }

我得到一个"Implicit conversion loses integer precision: 'NSUInteger' (aka 'unsigned long') to 'CC_LONG' (aka 'unsigned int')"警告。谁能给我一些指点,我可能在这里做错了什么?为什么我使用NSASCIIStringEncoding而不是NSUTF8StringEncoding的哈希密码字符串?

#define kSalt @"adlfu3489tyh2jnkLIUGI&%EV(&0982cbgrykxjnk8855"
    -(NSString*)hashPassword:(NSString*)password {
    //salt the password
    NSString* saltedPassword = [NSString stringWithFormat:@"%@%@", password, kSalt];
    //prepare the hashed storage
    NSString* hashedPassword = nil;
    unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
    //hash the pass
    NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding];
    if (CC_SHA1([data bytes], (unsigned)[data length], hashedPasswordData))
        {
        hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
    } else {
        [self promptUserMessage: @"Password can't be sent"];
        return @"Error";
    }
    NSLog(@"saltedPassword: %@",saltedPassword);
    NSLog(@"hashedPasswordData: %s",hashedPasswordData);
    NSLog(@"data: %@",data);
    NSLog(@"hashedPassword: %@",hashedPassword);
    return hashedPassword;
}
NSString* hashedPassword1 = [self hashPassword:@"abc"];

你的警告问题很好,值得深入研究如何探索它,因为其他人将来可能会有类似的问题。简短的答案是"将[data length]更改为(CC_LONG)[data length]",现在让我们看看为什么。

这是CC_SHA1的签名:

extern unsigned char *CC_SHA1(const void *data, CC_LONG len, unsigned char *md)

你是这样称呼它的:

if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {

-length是这样定义的:

@property NSUInteger length;

NSUInteger表示"无符号整数,此处理器上的字长"。在32位处理器上,它是32位无符号整数。在64位进程中,它是一个64位无符号整数。

CC_LONG的定义如下:

typedef uint32_t CC_LONG;       /* 32 bit unsigned integer */

所以它总是一个32位无符号整数

这在32位系统上没有问题,但在64位系统上,您将64位数字传递给32位参数。只要实际数字能在32位内,那就行得通。但是编译器并不确定这是真的,并且警告你如果它不是真的,你会得到意外的行为。修复方法是说"是的,我保证这个值将适合32位",你可以通过转换在C中做到这一点。您可以强制转换为一堆东西来摆脱警告,但最好是强制转换为所请求的内容,CC_LONG

if (CC_SHA1([data bytes], (CC_LONG)[data length], hashedPasswordData)) {

NSASCIIStringEncoding而言,这是一种非常糟糕的转换数据的方式,可能会丢失信息。我很惊讶这还能起作用。NSASCIIStringEncoding是7位ASCII,所以如果任何一个字节大于127(这是很有可能的),这种编码将失败。我不记得整个编码是否会失败,或者这些字节是否会被丢弃,但无论如何,它都不会是正确的答案。您也不能将其编码为UTF-8,但是一系列随机字节可能不是合法的UTF-8。要将随机数据转换为字符串,需要为此设计一种编码,例如base-64或十六进制。Base-64非常流行,因为它需要更少的字节来编码,同时产生7位ascii安全字符串。查看NSData上的-base64EncodedData:options:方法

最新更新