I know SHA-1 is preferred, but this project requires I use MD5.
#include
- (NSString*) MD5Hasher: (NSString*) query {
NSData* hash
cdespinosa and irsk have already shown you your actual problem, so let me go through your GDB transcript:
(gdb) p digest $1 = (unsigned char *) 0xa06310e4 "\0206b\260/\336\316^\021\b\a/9\310\225\204"
You've printed digest
as a C string. You can see here that this string is raw bytes; hence all the octal escapes (e.g., \020
, \225
) and the couple of punctuation characters (/
and ^
). It is not the printable ASCII hexadecimal representation you were expecting. You're lucky that there were no zero bytes in it; otherwise, you would not have printed the entire hash.
(gdb) po final Cannot access memory at address 0x0
final
is nil
. This makes sense, as your string above isn't valid UTF-8; again, it's just raw data bytes. stringWithUTF8String:
requires a UTF-8-encoded text string; you didn't give it one, so it returned nil
.
For passing raw data around, you'd use NSData. In this case, I think you want the hex representation, so you'll need to create that yourself the way irsk showed you.
Finally, consider how lucky you are that your input didn't hash to a valid UTF-8 string. If it had, you wouldn't have noticed this problem. You may want to construct a unit test for this hash method with this input.
(gdb) po digest Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_INVALID_ADDRESS at address: 0xb0623630 0x98531ed7 in objc_msgSend ()
Your program crashed (specific problem: “bad access”, “invalid address”) in objc_msgSend
. This is because digest
either is not a Cocoa/CF object at all or was one but was freed. In this case, it's because digest
is not a Cocoa object; it is a C array of bytes, as shown by your p digest
line above.
Remember, Objective-C is a superset of C. All of C exists unchanged in it. That means there are C arrays (e.g., char []
) and Cocoa's NSArrays side by side. Moreover, since NSArray comes from the Cocoa framework, not the Objective-C language, there's no way to make NSArray objects interchangeable with C arrays: You can't use the subscript operator on Cocoa arrays, and you can't send Objective-C messages to C arrays.
- (NSString*)MD5:(NSData *) data
{
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5([data bytes], (CC_LONG)data.length, md5Buffer);
// Convert unsigned char buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x",md5Buffer[i]];
return output;
}
How to use
NSString *yourStrToBeConverted;
NSData* data = [yourStrToBeConverted dataUsingEncoding:NSUTF8StringEncoding];
NSString *md5res=[self MD5:data];
These answers are correct but confusing. I post a working sample, since I had issues with most other answers. The code is tested and works well for Mac OS X 10.12.x and iOS 10.1.x.
YourClass.h
#import <CommonCrypto/CommonDigest.h>
@interface YourClass : NSObject
+ (NSString *) md5:(NSString *) input;
@end
YourClass.m
#import YourClass.h
+ (NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(cStr, (uint32_t)strlen(cStr), digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]]; //%02X for capital letters
return output;
}
Usage (e.g. in some other class):
SomeOtherClass.h
#import "YourClass.h"
SomeOtherClass.m
-(void) Test
{
//call by [self Test] or use somewhere in your code.
NSString *password = @"mypassword123";
NSString *md5 = [YourClass md5:password];
NSLog(@"%@", password);
NSLog(@"%@", md5);
}