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.
cost
operations and then compute the second $h$ bits usingcost
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. $\endgroup$