Morten Holmgaard
Morten Holmgaard

Reputation: 7806

MD5 hash not similar in C# and Objective C

My MD5 hashed string is the same in C# and Objective C.

In C#:

GetMD5("password123") // Equals: "f22ec811b8bf1cb6ac3aea13d3fcfebf"

private static string GetMD5(string text)
{
    UnicodeEncoding UE = new UnicodeEncoding();
    byte[] hashValue;
    byte[] message = UE.GetBytes(text);

    MD5 hashString = new MD5CryptoServiceProvider();
    string hex = "";

    hashValue = hashString.ComputeHash(message);
    foreach (byte x in hashValue)
    {
        hex += String.Format("{0:x2}", x);
    }
    return hex;
}

In Objective C:

[self md5HexDigest:@"password123"] // Equals: @"83878c91171338902e0fe0fb97a8c47a"  

+ (NSString*)md5HexDigest:(NSString*)input {
    const char* str = [input cStringUsingEncoding:NSUnicodeStringEncoding];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(str, strlen(str), result);

    NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
    for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
        [ret appendFormat:@"%02x",result[i]];
    }
    return ret;
}

I need to modify the Objective C version to match to C# version. What am I missing?

Upvotes: 2

Views: 721

Answers (2)

Rob
Rob

Reputation: 437542

There are two issues:

  1. The C# Unicode function returns a UTF-16 format using little endian byte order. Thus, use NSUTF16LittleEndianStringEncoding in Objective-C.

  2. Since this is a UTF16 string, using strlen will not work. You should use a NSData and then you can use length method:

    - (NSString*)md5HexDigest:(NSString*)input 
    {
        NSData *data = [input dataUsingEncoding:NSUTF16LittleEndianStringEncoding];
        unsigned char result[CC_MD5_DIGEST_LENGTH];
        CC_MD5([data bytes], [data length], result);
    
        NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
        for(int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
            [ret appendFormat:@"%02x",result[i]];
        }
        return ret;
    }
    

This will generate your f22ec811b8bf1cb6ac3aea13d3fcfebf value.

Upvotes: 4

nvoigt
nvoigt

Reputation: 77304

In C# you hash the bytes your unicode string consists of. In ObjC you somehow create an ANSI string and hash that. That's a difference. You need to change the ObjC version so that it gets the bytes from the unicode string and hashes those. Make sure C# and ObjC use the same Unicode convention (for example UTF16) both, or you will get further problems.

Upvotes: 0

Related Questions