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.