1

Here's a basic CC_SHA256 example:

-(void)hash:(NSData *)input
{
    NSLog(@"Input is %@", [self NSDataToHex:input]);

    NSMutableData *result = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];

    CC_SHA256(CFBridgingRetain(input), input.length, result.mutableBytes);

    NSLog(@"RESULT is %@", result);
}

This algorithm appears to be working correctly. A little test:

NSString* str = @"abcde";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];

[self hash:data];

NSString* str2 = @"fghijk";
NSData* data2 = [str2 dataUsingEncoding:NSUTF8StringEncoding];

[self hash:data2];

Gives the following output:

Input is 6162636465
RESULT is <91681b5f 162cf494 238e5cac 0debbe92 c3ede9bf 4bcc7e79 845b774f b33e99f7>
Input is 666768696A6B
RESULT is <cccf7b6f 9acb96ae 84e9852b 1a753825 d6750555 57175c78 f86cf5fb bb3cfca7>

Now, if I change the second argument (input.length) to 3, I get the following output:

Input is 6162636465
RESULT is <5e83c408 f722bb9a 9f602d85 c186bcb1 ebb8fa2f 0df2cc08 5eaf2522 92b01570>
Input is 666768696A6B
RESULT is <5e83c408 f722bb9a 9f602d85 c186bcb1 ebb8fa2f 0df2cc08 5eaf2522 92b01570>

These hashes are the same. I would expect the CC_SHA256 algorithm to just hash the first 3 characters of my input, but apparently, it doesn't work like that. Furthermore, if I relaunch the simulator, the hashes that are generated are different than the first time (but still equal to each other).

Why is this behaviour happening? Please don't give an (obvious) workaround for this problem. I really want to know why the algorithm behaves this way.

Dauntless
  • 300
  • 4
  • 17
  • 1
    I don't think you're passing in the right arguments for the hash. Try passing in `input.bytes` instead of `CFBridgingRetain(input)`. My guess is if you just pass in the reference of `input` you are hashing some internal data related to `NSData` and thus the first few bytes are the same and different between lanches. SHA should be deterministic so the fact that it is changing for the same input means you are using it incorrectly. – Jack Apr 14 '16 at 14:42
  • You appear to be right. I also thought the random nature was very weird. Can you add your answer so that I can mark it as correct? – Dauntless Apr 14 '16 at 14:50
  • The unfortunate part though, is that in the real application the input string is much longer (64 chars) and the input size is set to 32. Both (completely different) strings still give the same hash value... – Dauntless Apr 14 '16 at 14:51

1 Answers1

3

SHA (and any hashing algorithm) should be deterministic and so the fact that it varies between launches shows that you are likely using it incorrectly.

My guess is if you just pass in the reference of input you are hashing some internal data related to NSData and thus the first few bytes are the same but different between lanches.

Check out one of these other questions (Sha256 in Objective-C for iPhone) for a proper implementation of SHA-256 on iOS.

(from above answer):

-(NSString*)sha256HashFor:(NSString*)input
{   
    const char* str = [input UTF8String];
    unsigned char result[CC_SHA256_DIGEST_LENGTH];
    CC_SHA256(str, strlen(str), result);

    NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
    for(int i = 0; i<CC_SHA256_DIGEST_LENGTH; i++)
    {
        [ret appendFormat:@"%02x",result[i]];
    }
    return ret;
}
Community
  • 1
  • 1
Jack
  • 16,677
  • 8
  • 47
  • 51
  • Thanks for the answer. It is weird however that, for a large string, even the first 32 bytes of the object appear to be the same, as two different strings of length 64 both give the same hash – Dauntless Apr 14 '16 at 15:01