Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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
    1. Combine the random string with a timestamp so the hash is only valid for a set period of time
    2. 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?

share|improve this question
    
Why do you need MAC if you don't care for message integrity? A little bit more details about your security goals would be useful. –  K.Steff Oct 24 '12 at 1:15
    
It is a web service which does some processing/analysis on the 'message' and returns that information. The only security goal is to rate limit the API requests and have the ability to identify the user making the request (I.e. to allow different rate limits for different users) –  mrwooster Oct 24 '12 at 1:27
add comment

1 Answer

So you want to rate limit users. You really don't need to encrypt the message, then. You need a balancer.

If this is due to concerns about high traffic, you better implement it outside your server and use sth like haproxy, lighttpd or nginx. Nginx by default limits requests to 50/minute per IP, and redirects to a customizable 503 page. If IP suits you as an identity, that will be enough.

If IP isn't good, you can accept only requests with a solid key, then use haproxy as the sole balancer, or maybe 3scale which also provides analytics.

If high traffic or DoS, DDoS attacks are a concern for you, you can also use an apache server with mod_evasive as part of your proxy.

Finally, to be honest, there are so many possibilities that the IP is not a trustable id (NAT, users changing their IPs, even MACs). Since your main problem appears to be a decent authentication solution, why don't you use OpenID and a balancer?

Edit:

Nginx has also a limit_proxy_xuid option, which can be up to 255 characters, to limit traffic.

share|improve this answer
    
This isnt really what I am looking for. The authentication is to rate users to a certain threshold of requests, but I want to allow certain users to be allowed to have a different threshold. As far as I am aware, OpenID is for form based logins? –  mrwooster Oct 24 '12 at 16:02
    
Sorry if I misunderstood, but I saw rest tag on your question and Amazon, too, authenticates rest requests So, what is wrong with OpenID being for form based logins? After all, aren't you users going to send messages to your server as long as they are authenticated (logged in)? And if they may send messages anonymously, you can easily limit the threshold of the guest users. I also edited my answer to reflect rate-limiting capability of nginx based on userId instead of IP. –  barerd Oct 24 '12 at 16:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.