How do I create an MD5 Hash of a string in Cocoa?

前端 未结 9 1256
半阙折子戏
半阙折子戏 2020-11-28 04:25

I know SHA-1 is preferred, but this project requires I use MD5.

#include 

- (NSString*) MD5Hasher: (NSString*) query {
    NSData* hash         


        
相关标签:
9条回答
  • 2020-11-28 05:15

    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.

    0 讨论(0)
  • 2020-11-28 05:28
    - (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];
    
    0 讨论(0)
  • 2020-11-28 05:32

    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);
    }
    
    0 讨论(0)
提交回复
热议问题