4
votes

So, I want to secure a http json web service.

I will have a bunch of users of the system who will all have a username and password. I only want to store a randomly salted hash of user's passwords in my database so as to avoid all passwords being discovered in the case of the database being compromised, and a salt (per password) to avoid pre-computed rainbow tables / dictionary attacks.

I've been looking at digest authentication as it has the benefit of preventing replay attacks by the use of random 'nonce' provided by the server to the client, like so:

A1 = string.hashMD5 (username + ":" + realm + ":" + password)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

However, in order for the server to re-compute 'requestdigest', it must know 'password', but my server will only have access to a salted hash.

If I was not using a salt, I could add a further step on the client side like so (because on the client side the password is known) -

HashedPword = string.hashMD5(password)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

And then on the server side I could retrieve the Hashed password from the db to perform the re-computation.

Alas, the client would need to know the salt as well in order to do it properly which would be e.g.

HashedSaltedPword = string.hashMD5(password+salt)
A1 = string.hashMD5 (username + ":" + realm + ":" + HashedSaltedPword)
A2 = string.hashMD5 (paramTable.method + ":" + paramTable.uri)
requestdigest = string.hashMD5 (A1 + ":" + nonce + ":" + A2)

So that leaves transmitting the salt to the client without authentication by maybe exposing a web service function that returns the salt, given a username. But then anyone could get access to the salts.

What i'm wondering though is if giving out the salts is a problem or not. Because, the salt on it's own is useless without the hash stored in the database, and if the database is compromised, then the attacker would have access to both the hashes and salt anyway. And following on from that, if I give away the salt for free, then I may as well just use the username itself AS the salt, as that would be unique per user - and thus I wouldn't even need to expose a webservice call to discover the salt in the first place.

What do you guys think? Does exposing salts or having a known salting mechanism matter? Any other thoughts?

I'm not really worried about the downside to digest authentication - i.e. that the client does not know if it is talking to the 'real' server or not. Because, it's not like the client's password is going to be exposed using this method, and i'm not asking the client for anything confidential over this link like a credit card. I.e. stuff i want to secure resides on my server, and the server won't be asking the client for any of THEIR secure information.

Edit: hmm, actually i just read this link Salt, passwords and security which does basically confirmed to me that knowing the salt does not matter. So i'm thinking of implementing some sortof hash like:

HashedSaltedPword = string.hashMD5(password+username+siteWideSaltExistingOnlyInCode)

The addition of the site-wide salt is in case someone has created rainbow tables for common username's. Does this approach seem secure?

1
Your question doesn't have much to do with JSON, does it? I think it's perhaps a bit long & heavy. It seems you are really asking "How can I use Digest Authentication when I only store encrypted passwords?"Kirk Broadhurst

1 Answers

0
votes

You must choose how do you want transmit password. Do you want to transmit it only hashed from client side to the server side? In such case server must store passwords otherwise it will not be able to recompute the hash. Do you want server to not store passwords? In such case you must transfer the password in the plain text so that server can compute the hash and compare it with stored one.

The former case requires stored passwords in database and if you want to secure them you should use some database / application level encryption. The later case requires secured transport (HTTPS, VPN, etc.) because passwords are transmitted in readable form.