I know SHA-1 is preferred, but this project requires I use MD5.
#include
- (NSString*) MD5Hasher: (NSString*) query {
NSData* hash
Facebook uses this
#import <CommonCrypto/CommonDigest.h>
+ (NSString*)md5HexDigest:(NSString*)input {
const char* str = [input UTF8String];
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;
}
Or instance method
- (NSString *)md5 {
const char* str = [self UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)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;
}
This is the category I use:
NSString+MD5.h
@interface NSString (MD5)
- (NSString *)MD5String;
@end
NSString+MD5.m
#import <CommonCrypto/CommonDigest.h>
@implementation NSString (MD5)
- (NSString *)MD5String {
const char *cStr = [self UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5( cStr, (CC_LONG)strlen(cStr), result );
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
@end
Usage
NSString *myString = @"test";
NSString *md5 = [myString MD5String]; // returns NSString of the MD5 of test
I believe that digest is a pointer to a raw binary hash. In the next line you're attempting to interpret it as a UTF-8 string, but it is most likely not to contain legal UTF-8-encoded character sequences.
I expect what you want is to convert the 16-byte static array of unsigned char into 32 ASCII hexadecimal characters [0-9a-f] using whatever algorithm you see fit.
@implementation NSString (MD5)
+ (NSString *)formattedMD5:(const char *)data length:(unsigned long)len
{
unsigned char *digest = MD5((unsigned const char *)data, len, NULL);
NSMutableArray *values = [[NSMutableArray alloc] init];
for (int i = 0; i < strlen((char *)digest); i++)
{
char hexValue[4];
sprintf(hexValue, "%02X", digest[i]);
[values addObject:[NSString stringWithCString:hexValue length:strlen(hexValue)]];
}
// returns a formatted MD5 fingerprint like
// 00:00:00:00:00:00:00:00:00
return [values componentsJoinedByString:@":"];
}
@end
I had used this method:
NSString+MD5.h
@interface NSString (MD5)
- (NSString *)MD5;
@end
NSString+MD5.m
#import "NSString+MD5.h"
#import <CommonCrypto/CommonDigest.h>
@implementation NSString (MD5)
- (NSString *)MD5 {
const char * pointer = self.UTF8String;
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(pointer, (CC_LONG)strlen(pointer), md5Buffer);
NSMutableString * string = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[string appendFormat:@"%02x", md5Buffer[i]];
}
return string;
}
@end
Usage:
NSString * myString = @"test";
NSString * md5 = [myString MD5];
The MD5 function does not return a C string, it returns a pointer to some bytes. You can't treat it as a string.
If you want to create a string, you need to build a string using the hex values of those bytes. Here is one way to do it as a category on NSData:
#import <CommonCrypto/CommonDigest.h>
@implementation NSData (MMAdditions)
- (NSString*)md5String
{
unsigned char md5[CC_MD5_DIGEST_LENGTH];
CC_MD5([self bytes], [self length], md5);
return [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
md5[0], md5[1],
md5[2], md5[3],
md5[4], md5[5],
md5[6], md5[7],
md5[8], md5[9],
md5[10], md5[11],
md5[12], md5[13],
md5[14], md5[15]
];
}
@end