简体   繁体   中英

CC_SHA1 hashing a password and implicit conversion loss in iOS

I am trying to hash a password and following a tutorial. I have #define kSalt @"adlfu3489tyh2jnkLIUGI&%EV(&0982cbgrykxjnk8855" to add to my password and I hash like so:

    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");
    }

I am getting an "Implicit conversion loses integer precision: 'NSUInteger' (aka 'unsigned long') to 'CC_LONG' (aka 'unsigned int')" warning. Could someone give me some pointers to what I might be doing wrong here please? And also why am I using NSASCIIStringEncoding and not NSUTF8StringEncoding for the hashedPassword string?

#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"];

Your warning question is a good one, and worth digging into how to explore it since others may have similar questions in the future. The short answer is "change [data length] to (CC_LONG)[data length] ." Now let's see why.

Here's the signature for CC_SHA1 :

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

Here's how you're calling it:

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

And here's how -length is defined:

@property NSUInteger length;

NSUInteger means "unsigned integer, the word size on this processor." So on a 32-bit processor, it's 32-bit unsigned integer. On a 64-bit process, it's a 64-bit unsigned integer.

CC_LONG is defined this way:

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

So it's always a 32-bit unsigned integer.

This has no problem on a 32-bit system, but on a 64-bit system you're passing a 64-bit number to a 32-bit parameter. As long as the actual number fits inside 32 bits, that's going to work. But the compiler doesn't know for certain that this is true and is warning you that you'll get unexpected behavior if it isn't true. The fix is to say "yes, I promise this value will fit in 32 bits" and you do that in C by casting. You could cast to a bunch of things to get rid of the warning, but the best is to cast to exactly what is requested, CC_LONG .

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

As far as NSASCIIStringEncoding goes, this is a really bad way to convert the data, and probably loses information. I'm surprised this even works at all. NSASCIIStringEncoding is 7-bit ASCII, so if any of the bytes are greater than 127 (which is quite likely), this encoding will fail. I can't remember if the whole encoding will fail, or if those bytes will just be dropped, but either way, it's not going to be the right answer. You can't encode it as UTF-8 either, but a series of random bytes will likely not be legal UTF-8. To convert random data into a string, you need an encoding designed for that, such as base-64 or hex. Base-64 is very popular because it requires fewer bytes to encode while resulting in a 7-bit ASCII-safe string. Look at the -base64EncodedData:options: method on NSData .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM