Question

I'm trying to translate some hashcode that is written with .NET into Objective-c Syntax

SHA1 sha1 = new SHA1CryptoServiceProvider();
   string hashedword = Convert.ToBase64String(sha1.ComputeHash(Encoding.ASCII.GetBytes(saltkey)))

This is what I have so far

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

At the end I want an hashed NSString.

Can somebody help me with this ?

Was it helpful?

Solution

The NSUnicodeStringEncoding conversions look suspicious in your code and seem to be unnecessary. You have to use the same encoding as your .NET code.

I cannot test this with .NET, but according to the documentation, Encoding.ASCII uses the replacement character ? for all non-ASCII characters.

There is no equivalent NSStringEncoding, but the same result can be achieved with CoreFoundation methods:

NSString *password = ... // your password

CFIndex asciiLength;
// Determine length of converted data:
CFStringGetBytes((__bridge CFStringRef)(password), CFRangeMake(0, [password length]),
                 kCFStringEncodingASCII, '?', false, NULL, 0, &asciiLength);
// Allocate buffer:
uint8_t *asciiBuffer = malloc(asciiLength);
// Do the conversion:
CFStringGetBytes((__bridge CFStringRef)(password), CFRangeMake(0, [password length]),
                 kCFStringEncodingASCII, '?', false, asciiBuffer, asciiLength, NULL);

Now you can compute the SHA1 hash:

unsigned char hash[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(asciiBuffer, asciiLength, hash);
free(asciiBuffer);
NSData *result = [NSData dataWithBytes:hash length:CC_SHA1_DIGEST_LENGTH];

And finally the Base64-encoded string from the hash. Starting with iOS 7, there is a built-in method:

NSString *base64 = [result base64EncodedStringWithOptions:0];

A better option would be to use the UTF-8 encoding instead of ASCII encoding (for both .NET and Objective-C). In that case the code would simplify to

NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
unsigned char hash[CC_SHA1_DIGEST_LENGTH];
CC_SHA1([data bytes], [data length], hash);
NSData *result = [NSData dataWithBytes:hash length:CC_SHA1_DIGEST_LENGTH];
NSString *base64 = [result base64EncodedStringWithOptions:0];

If the password contains only ASCII characters, both methods give the same result.

OTHER TIPS

If you need that final base-64 string, you can use this code, which either calls the new iOS 7 base64EncodedStringWithOptions or calls the now deprecated (and previously private) base64Encoding method in earlier versions:

NSString *string;

if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
    string = [result base64EncodedStringWithOptions:kNilOptions];  // iOS 7+
} else {
    string = [result base64Encoding];                              // pre iOS7
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top