I am designing a simple webservice and want to use HMAC for authentication to the service.
For the purpose of this question we have:
- a web service at example.com
- a secret key shared between a user and the server [K]
- a consumer ID which is known to the user and the server (but is not necessarily secret) [D]
- a message which we wish to send to the server [M]
The standard HMAC implementation would involve using the secret key [K] and the message [M] to create the hash [H], but I am running into issues with this. The message [M] can be quite long and tends to be read from a file. I have found its very difficult to produce a correct hash consistently across multiple operating systems and programming languages because of hidden characters which make it into various file formats. This is of course bad implementation on the client side (100%), but I would like this webservice to be easily accessible and not have trouble with different file formats.
I was thinking of an alternative, which would allow the use a short (5-10 char) random string [R] rather than the message for autentication, e.g.
H = HMAC(K,R)
The user then passes the random string to the server and the server checks the HMAC server side (using random string + shared secret).
As far as I can see, this produces the following issues:
- There is no message integrity - this is ok message integrity is not important for this service
- A user could re-use the hash with a different message - I can see 2 ways around this
- Combine the random string with a timestamp so the hash is only valid for a set period of time
- Only allow each random string to be used once
- Since the client is in control of the random string, it is easier to look for collisions
I should point out that the principle reason for authentication is to implement rate limiting on the API service. There is zero need for message integrity, and its not a big deal if someone can forge a single request (but it is if they can forge a very large number very quickly).
I know that the correct answer is to make sure the message [M] is the same on all platforms/languages before hashing it. But, taking that out of the equation, is the above proposal an acceptable 2nd best?