1

According to this site mysql uses:

SHA1(UNHEX(SHA1("this_is_a_random_string")))

To generate its password() hash.

...

I have copied this function, from another StackOverflow post:

- (NSString *)sha1:(NSString *)str {
    const char *cStr = [str UTF8String];
    unsigned char result[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(cStr, strlen(cStr), result);
    NSString *s = [NSString  stringWithFormat:
                  @"%02X%02X%02X%02X%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],
                  result[16], result[17], result[18], result[19]
                  ];

    return s;
}

To generate sh1 hashes. But as the first link says:

the second SHA1() is applied to the binary data returned by the first SHA1() and not to its hex representation. Therefore in SQL I have to UNHEX() it before applying the second SHA1.

So I have to do something like:

NSString * a = [self sha1:@"abc"];
// convert a into binary data.
NSString * b = [self:sha1:a];

But whatever I try I cannot get it to work.

What is the simplest way to do this?

Cœur
  • 37,241
  • 25
  • 195
  • 267
A.D
  • 2,150
  • 3
  • 13
  • 19

1 Answers1

1
- (NSString *)mysqlHashFromString:(NSString *)password{
    NSString *sha1String = [self sha1:password];
    NSData *sha1StringBinaryRepresentation = [self dataWithString:sha1String];
    NSString *finalHash = [self hexStringValue:[self SHA1Digest:sha1StringBinaryRepresentation ]];
    return finalHash;
} 

- (NSData *)dataWithString:(NSString *)string {
   NSString *command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
   NSMutableData *commandToSend = [NSMutableData new];
   unsigned char whole_byte;
   char byte_chars[3] = {'\0','\0','\0'};
   int i;
   for (i=0; i < [command length]/2; i++) {
       byte_chars[0] = [command characterAtIndex:i*2];
       byte_chars[1] = [command characterAtIndex:i*2+1];
       whole_byte = strtol(byte_chars, NULL, 16);
       [commandToSend appendBytes:&whole_byte length:1]; 
   }
   return commandToSend;
}

- (NSString *)sha1:(NSString *)plainTextPasssword{
    NSData *data = [plainTextPasssword dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(data.bytes, data.length, digest);
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [output appendFormat:@"%02x", digest[i]];
    }
    return output;
}

- (NSData *)SHA1Digest:(NSData *)data {
    unsigned char result[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([data bytes], [data length], result);
    return [NSData dataWithBytes:result length:CC_SHA1_DIGEST_LENGTH];
}

- (NSString *)hexStringValue:(NSData *)data {
    NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([data length] * 2)];
    const unsigned char *dataBuffer = [data bytes];
    for (int i = 0; i < [data length]; ++i) {
        [stringBuffer appendFormat:@"%02x", (unsigned long)dataBuffer[i]];
    }

    return [stringBuffer copy];
}

Creating SHA1 Hash from NSString
Converting HEX NSString To NSData
https://github.com/ali-rantakari/Tagger/blob/master/NSData%2BSHA1.m

Community
  • 1
  • 1
StefanS
  • 1,089
  • 1
  • 11
  • 38
  • I used your code and added `NSString * b = [self sha1:[NSString stringWithFormat:@"%@",commandToSend]];` to the end of it. I'm getting the hash `25EE266DD57C5647042A1F73AE7149194D3C0842` But when I run `select password('abc');` on mysql I get: `*0D3CED9BEC10A777AEC23CCC353A8C08A633045E` – A.D May 09 '16 at 14:47
  • you need to apply the sha1 function from the above github url on nsdata in order to get the correct hash. – StefanS May 09 '16 at 14:48
  • Don't know what github url you mean. Can you add the code on your post instead? – A.D May 09 '16 at 14:54
  • my mistake : you also need to do NSData *data = [command dataUsingEncoding:NSUTF8StringEncoding]; NSString *finalHash = [self sha1_nsdata:data]; – StefanS May 09 '16 at 14:55
  • done, updated code, i'm on Windows right now, can't test. please provide feedback if something's off. – StefanS May 09 '16 at 15:02
  • 1
    Hey thank you very much! I do not have any more time today to work on this, but I'll try that tomorrow – A.D May 09 '16 at 15:04
  • 1
    I tried your code. And it worked perfectly! (thank you!). I made some small changes, ex. finalHash var to : `NSString *finalHash = [[NSString stringWithFormat:@"*%@", [self hexStringValue:[self SHA1Digest:sha1StringBinaryRepresentation ]]] uppercaseString];` To make it identical to Mysql. I also removed `NSString *command = [string stringByReplacingOccurrencesOfString:@" " withString:@""];` in the `dataWithString` function because I don't think it's needed (correct me if I'm wrong). – A.D May 10 '16 at 07:16
  • 1
    Great :-) i didn't even test it, glad it worked in the first run. – StefanS May 10 '16 at 07:43