1

I'm currently developing an app which needs to send authentication data with it to a provided API. Basically it needs to generate a hash based on the data you want to send, based on a shared key.

The problem is that while I have been able to track down functions that will do MD5 hashing, they are not based on a key, which is absolutely crucial.

Is there any way this can be done in objective-c for the iOS platform?

The API is usually used with PHP, which provides something like this handy function:

$key = hash_hmac('md5', $postdata , $sharedkey);

Is there any chance of implementing an equal in objective-c?

sarnold
  • 102,305
  • 22
  • 181
  • 238
CodingBeagle
  • 1,888
  • 2
  • 24
  • 52
  • Check this [forum](https://discussions.apple.com/thread/1509152?start=0&tstart=0) out – Joel Kravets Feb 11 '12 at 00:32
  • hmmm yes they mention the use of the function CC_MD5([self bytes],[self length],digest), which is what I am using now. But it does not seem to be able to generate based on a key as parameter? – CodingBeagle Feb 11 '12 at 00:34
  • possible duplicate of [Objective-C sample code for HMAC-SHA1](http://stackoverflow.com/questions/756492/objective-c-sample-code-for-hmac-sha1) – sarnold Feb 11 '12 at 01:06
  • There are a fair number of `hmac` questions on SO, several include source: http://stackoverflow.com/search?q=HMAC+%5Bobjective-c%5D&submit=search – Nathan Kinsinger Feb 11 '12 at 02:43

2 Answers2

4

The MD5 algorithm only uses one string as input. The convention is that you append your key (aka "salt" value) to the string you are hashing. My guess is that the PHP MD5 function has a second parameter for the key to make life easier, but you should get the same result if you just do this:

NSString *value = [data stringByAppendingString:key];
NSString *hashed = MD5HASH(value); //pseudocode

UPDATE:

Okay, I checked Wikipedia and it looks like you need to do a bit of extra work to implement HMAC-style hashing. So you have two options.

  1. Implement the HMAC algorithm on top of the MD5 hash you're already using (it doesn't look too hard - I've pasted the pseudocode below).

  2. Don't bother with HMAC - just generate the hash at both ends using a regular MD5 by concatenating the message and the key - that should be pretty secure, it's what most people do.

HMAC algorithm

function hmac (key, message)
    if (length(key) > blocksize) then
        key = hash(key) // keys longer than blocksize are shortened
    end if
    if (length(key) < blocksize) then
        key = key ∥ [0x00 * (blocksize - length(key))] // keys shorter than blocksize are zero-padded ('∥' is concatenation) 
    end if

    o_key_pad = [0x5c * blocksize] ⊕ key // Where blocksize is that of the underlying hash function
    i_key_pad = [0x36 * blocksize] ⊕ key // Where ⊕ is exclusive or (XOR)

    return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) // Where '∥' is concatenation
end function
Nick Lockwood
  • 40,865
  • 11
  • 112
  • 103
  • Thank you a lot for the answer :) In the end we went with the second option, but not bothering with HMAC, and simply generate the hash using regular MD5 :) – CodingBeagle Feb 14 '12 at 16:01
1

Typically you just append the key to the bytes that you are hashing.

So if the shared secret is "12345" and you are passing username=jsd and password=test you would construct your string like "username=jsd&password=test&secret=12345". Then the receiving end would construct its own version from the username & password + the secret, run the same md5, and receive the same value.

jsd
  • 7,673
  • 5
  • 27
  • 47