1

Basically I want to write function that computes sha1 hash.

So far I have tried is as follows.

C#.NET

byte[] p2 = System.Text.Encoding.Unicode.GetBytes("password");
System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();
byte[] result = sha.ComputeHash(p2);
string encodedPassword = Convert.ToBase64String(result);

Output : 6Pl/upEE0epQR5SObftn+s2fW3M=

Objective-C

I have added classes for Base64 from NSData_Base64 Classes reference.

NSString *password = @"password";
NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
NSString *unicodePassword = [[NSString alloc] initWithData:data encoding:NSUnicodeStringEncoding];
data = [unicodePassword dataUsingEncoding:NSUnicodeStringEncoding];


unsigned char hash[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([data bytes], [data length], hash);
NSData *result = [NSData dataWithBytes:hash length:CC_SHA1_DIGEST_LENGTH];
NSLog(@"Result: %@",[result base64EncodedString]);

Output : dYusXVhObIBzJMgg1E1FJ9cK1NY=

Can anyone please suggest what am I doing wrong ?

Why these two values differs ?

Please correct my mistakes.

βhargavḯ
  • 9,786
  • 1
  • 37
  • 59
  • maybe "NSData_Base64 Classes reference" works with URL safe base64, but C#.NET's System.Security.Cryptography.SHA1 works with URL-unsafe one? Try using online SHA1 encryptors/decryptors to compare results. I am suggesting to use GData Base64 that can be found here: https://code.google.com/p/gdata-objectivec-client/. – art-divin Apr 17 '13 at 13:27

2 Answers2

3

This line is wrong, since you interpret UTF8 encoded data as if it was Unicode encoded:

NSString *unicodePassword = [[NSString alloc] initWithData:data encoding:NSUnicodeStringEncoding];

Replce the second line with: NSData *data = [password dataUsingEncoding:NSUnicodeStringEncoding];

The 2 first bytes in data is a BOM (Byte order mark).

Remove these 2 bytes with data = [NSData dataWithBytes:[data bytes] + 2 length:[data length] - 2];

...and then hash that data any you will have the same hash as in C#.

Markus
  • 528
  • 1
  • 5
  • 10
1

For further information I found that SHA1 function can have some results..

So I have implemented methods at this link: MD5 and SHA1 iOS implementation linked by this stackoverflow question

and I refine it with my integration that send as parameters if you send UTF8-encoding string or not (unicode one) and if you want hexadecimal string or decimal one

- (NSString*) sha1UTF8Encoding:(BOOL)utf8 andDecimal:(BOOL)decimal
{
    const char *cstr;
    if (utf8) {
        cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    }else{
        cstr = [self cStringUsingEncoding:NSUnicodeStringEncoding];
    }
    NSData *data = [NSData dataWithBytes:cstr length:self.length];

    uint8_t digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1(data.bytes, data.length, digest);

    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

    for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++){
        if (decimal) {
            [output appendFormat:@"%i", digest[i]];
        }else{
            [output appendFormat:@"%02x", digest[i]];
        }
    }

    return output;    
}

(Note that I implemented this method in a NSString Category)

With this I tested that you can use it for many purpose sha1 operation, for example with this configuration:

NSString* sha1 = [stringToTest sha1UTF8Encoding:YES andDecimal:YES];

sha1 variable match with the one product by the C# method found at this link: Hashing using the SHA1 class

Community
  • 1
  • 1
ricky.tribbia
  • 124
  • 10