2

I have been following a couple of articles regarding RESTful web services with WCF and more specifically, how to go about authentication in these. The main article I have been referencing is Aaron Skonnard's RESTful Web Services with WCF 3.5. Another one that specifically deals with HMAC authentication is Itai Goldstiens article which is based on Skonnards article.

I am confused about the "User Key" that is referenced to in both articles. I have a client application that is going to require a user to have both a user name and password.

  • Does this then mean that the key I use to initialise the System.Security.Cryptography.HMACMD5 class is simply the users password?
  • Given the method used to create the Mac in Itai's article (shown below), am I right is thinking that key is the users password and text is the string we are using confirm that the details are in fact correct?

    public static string EncodeText(byte[] key, string text, Encoding encoding)
    {
        HMACMD5 hmacMD5 = new HMACMD5(key);
        byte[] textBytes = encoding.GetBytes(text);
        byte[] encodedTextBytes =
            hmacMD5.ComputeHash(textBytes);
        string encodedText =
            Convert.ToBase64String(encodedTextBytes);
        return encodedText;
    }
    

In my example, the text parameter would be a combination of request uri, a shared secret and timestamp (which will be available as a request header and used to prevent replay attacks).

Is this form of authentication decent? I've come across another thread here that suggests that the method defined in the articles above is "..a (sic) ugly hack." The author doesn't suggest why, but it is discouraging given that I've spent a few hours reading about this and getting it working. However, it's worth noting that the accepted answer on this question talks about a custom HMAC authorisation scheme so it is possible the ugly hack reference is simply the implementation of it rather than the use of HMAC algorithms themselves.

The diagram below if from the wikipedia article on Message Authentication Code. I feel like this should be a secure way to go, but I just want to make sure I understand it's use correctly and also make sure this isn't simply some dated mechanism that has been surpassed by something much better.

Illustrates how MAC authentication works between sender and reciever

Community
  • 1
  • 1
Mr Moose
  • 5,946
  • 7
  • 34
  • 69

1 Answers1

4

The key can be the user's password, but you absolutely should not do this.

  • First - the key has an optimal length equal to the size of the output hash, and a user's password will rarely be equal to that.
  • Second, there will never be enough randomness (entropy to use the technical term) in those bytes to be an adequate key.
  • Third, although you're preventing replay attacks, you're allowing anyone potentially to sign any kind of request, assuming they can also get hold of the shared secret (is that broadcast by the server at some point or is it derived only on the client and server? If broadcast, a man-in-the-middle attack can easily grab and store that - height of paranoia, yes, but I think you should think about it) unless the user changes their password.
  • Fourth - stop using HMACMD5 - use HMAC-SHA-256 as a minimum.

This key should at the very least be a series of bytes that are generated from the user's password - typically using something like PBKDF2 - however you should also include something transitory that is session-based and which, ideally, can't be known by an attacker.

That said, a lot of people might tell you that I'm being far too paranoid.

Personally I know I'm not an expert in authentication - it's a very delicate balancing act - so I rely on peer-reviewed and proven technologies. SSL (in this case authentication via client certificates), for example, might have it's weaknesses, but most people use it and if one of my systems gets exploited because of an SSL weakness, it's not going to be my fault. However if an exploit occurs because of some weakness that I wasn't clever enough to identify? I'd kick myself out of the front door.

Indidentally, for my rest services I now use SCRAM for authentication, using SHA512 and 512 bits of random salt for the stretching operation (many people will say that's excessive, but I won't have to change it for a while!), and then use a secure token (signed with an HMAC and encrypted with AES) derived from the authentication and other server-only-known information to persist an authenticated session. The token is stateless in the same way that Asp.Net forms authentication cookies are.

The password exchange works very well indeed, is secure even without SSL (in protecting the password) and has the added advantage of authenticating both client and server. The session persistence can be tuned based on the site and client - the token carries its own expiry and absolute expiry values within it, and these can be tuned easily. By encrypting client ID information into that token as well, it's possible to prevent duplication on to another machine by simply comparing the decrypted values from the client-supplied values. Only thing about that is watching out for IP address information, yes it can be spoofed but, primarily, you have to consider legitimate users on roaming networks.

Community
  • 1
  • 1
Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
  • thanks for your answer. I'd just like to clarify a couple of other things. If I used PBKDF2 to generate a sufficiently large key, am I right in thinking that the PBKDF2 algorithm on both the client and server will produce the same result? I'm helping write the WCF service, but will have no involvement in the iPhone client application. I hope that'll cover points 1 and 2. For point 3, the shared secret will be part of the iPhone app and WCF's configuration and won't be broadcast. As for number 4, I'll blame http://www.codinghorror.com/blog/2009/05/the-bathroom-wall-of-code.html – Mr Moose Mar 29 '12 at 13:57
  • Hi - the PBKDF2 algorithm will indeed generate the same result - however it should be noted that the .Net implementation `RFC2898DeriveBytes`(http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx) is fixed to only one hash function, whereas officially you should be able to choose your own - there are other implementations around if you Google. 3) Having the secret compiled into the app is not advisable - decompilers exist :) - better to use a random nonce that is only good for that one session – Andras Zoltan Mar 30 '12 at 07:51
  • do you know if it is common (or advisable) to use PBKDF2 functions on a mobile device (ie. iPhone/Android). When writing a simple browser based javascript test client, I've noticed it can be quite slow in some browsers. I imagine this will be exacerbated on a mobile device. On another [thread of mine](http://security.stackexchange.com/q/13590/8956), it was suggested that PBKDF2 "...would be a very poor choice because it would add significant CPU usage". I'd appreciate your opinion on it's suitability. – Mr Moose Apr 10 '12 at 06:30
  • Indeed the the point of PBKDF2 is to make the client do the work. The iPhone itself uses PBKDF2 to derive keys for the encrypted personal storage. The solution here is to do it only when you need to - so, for example, at the application startup; or once every day - use PBKDF2 (perhaps getting the parameters from the server) to derive your key. Equally you could do it on first-run, storing the result in the user's encrypted storage. – Andras Zoltan Apr 10 '12 at 09:12
  • Doh. I think I might have misused PBKDF2 then. I've essentially run PBKDF on the password with the salt being a combination of sharedsecret and timestamp (to make it dynamic). Maybe you are correct in that I should simply do it on app startup, and then add the dynamic elements to the HMAC algorithm and have a constant salt (maybe in the form of a nonce). Gee I feel like I am just making this all up as I go. Thanks again for your input. – Mr Moose Apr 10 '12 at 09:34
  • 'I feel like I am just making this all up as I go' - yep I know that feeling :) – Andras Zoltan Apr 10 '12 at 09:41