For a variety of reasons, I need to use digest authentication for a REST server that I have created.
I have come up with an "improvement" that I believe strengthens the algorithm against MD5 attacks without being a burden on clients. What problems can you see with my algorithm?
- Client is a custom application written in C#.
- Server is a JAX-RS-based REST Server written in Java and running on Tomcat.
- All traffic between the client and server is encrypted using SSL/TLS.
The database contains a user_table with the following columns:
- user_id: primary key
- password_hash: varchar not null
- salt: varchar not null
- iteration_count: integer
Digest Authentication (RFC2617)
Digest authentication uses the following calculations:
nonce: server-generated number used once nonceCount: server-generated increasing value (prevents replay attacks) cnonce: client-generated number used once qop: quality of protection ("auth") method: typically one of "GET", "POST", "PUT", etc. HA1 = MD5(username:realm:password) HA2 = MD5(method:digestURI) response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
HA1 value is stored in the database as the password hash value. During authentication, the client calculates the value of
response from the
WWW-authenticate http headers. The server also calculates the
response value using its stored version of
HA1 and compares the value received from the client. If they are equal, the client is authenticated.
MD5 is no longer considered secure. Collisions can be found in a few hours using commodity hardware.
Using PBKDF2 to Strengthen Digest
- Client obtains the username and plaintext password from the user.
- Client requests the salt and iteration count for the user_id from the server. The server also sends the current default iteration count (which may be different than that used for this user).
- Client calculates a 128-bit secret key using PBKDF2(password, salt, user-specific iteration count). The secret key is encoded as a hexadecimal string.
- Client calculates
HA1using the username, realm, and hexadecimal-encoded key. This
HA1value is used in a standard digest authentication.
- Server obtains the password hash from the database. The password hash is the previously calculated
HA1using the same PBKDF2-derived secret key. The server compares the calculated
responsevalue sent by the client (standard digest authentication). If the two
responsevalues are equal, the client is authenticated.
- If the user-specific iteration count returned to the client is different than the default iteration count, the client calculates a new
HA1using PBKDF2 and the new iteration count. The client calls a
PUTmethod on the REST Server to update the password hash column using the new value. This step allows the algorithm to be updated with larger iteration counts as hardware get faster.
The modified algorithm does not rely on the strength of MD5 to protect the password hash, since the difficulty of calculating the password hash is dependent on PBKDF2 (which can use a SHA-1 or SHA-256 hash).
Are there any obvious security flaws in this modified algorithm?