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.

  • $\begingroup$ 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. $\endgroup$
    – SEJPM
    Commented Jun 23, 2017 at 12:07
  • 2
    $\begingroup$ Maybe we should make up a hashtag for this kind of question: #whynotTLS? $\endgroup$
    – Elias
    Commented Jun 23, 2017 at 12:36

1 Answer 1


Here are my comments in no particular order:

  1. Don't create your own crypto.
  2. We don't analyze designs on this website because it is hard work and you shouldn't create your own anyway.
  3. It seems that for this protocol to work the server will have to store the user password in plaintext. That seems like a bad idea.
  4. Using this scheme will allow an attacker to brute force the user password using only the information that has been transmitted since he can validate

    auth_key = PBKDF2(password_guess, salt, cost, 768))

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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.