# Ensuring no unintended leaking before authentication

Assume my authentication system consists of querying an endpoint to get sign in parameters cost and salt, auth_hash.

After receiving these parameters, I will use cost and salt to derive a 768 bit key using PBKDF2:

key = pbkdf2(user_password, salt, cost, 768).hex


I then split the key three ways:

server_password = key.first_third
encryption_key = key.second_third
auth_key = key.third_third


I will then use auth_key to authenticate the parameters sent from the server and make sure the computed authentication hash matches the incoming auth_hash:

local_auth_hash = HMAC(cost.to_string + salt, auth_key)
abort if local_auth_hash != auth_hash


Now, during normal app flow, I will encrypt user data with encryption_key and authenticate it with auth_key.

My question is, is it safe to use auth_key in both of these contexts (sign in and data encryption)? The reason I would suspect that it might not be ok is that the server can return any cost and salt, and have me authenticate it with my auth_key, and potentially try to glean information this way.

• Note that querying large amounts (ie larger than the PRF's output bit-length $h$) of keying material directly from PBKDF2 is a bad idea. The reason is that it will essentially compute the first $h$ bits using cost operations and then compute the second $h$ bits using cost operations. So an attacker can probably just compute the first part of the key to verify his guesses while your user has to compute 2*cost operations. The fix is to use PBKDF2 to output $h$ bits of keying material and then run PBKDF2 with 1 iteration on the result to expand it. – SEJPM Jun 23 '17 at 12:07
• Maybe we should make up a hashtag for this kind of question: #whynotTLS? – Elias Jun 23 '17 at 12:36

auth_key = PBKDF2(password_guess, salt, cost, 768))
HMAC(cost.to_string + salt, auth_key) == auth_hash. That also seems like a bad idea.