I'm trying to generate AES256 key from user input password. The size of the password can be anything from 4 bytes long to 32 bytes long but let's assume it is the smaller one. My API support either : SP800-108 HMAC in counter mode, SP800-56A, PBKDF2 or CAPI_KDF According to several articles I read, the common PBKDF2 suffers from multiple weaknesses and so it's not an option. I would like to know which one from the above is the most secure KDF for my purpose. In addition I would like to know what the relations between the algorithms above to Argon2 and Scrypt.

Thank you in advance :)


You need a key stretching function, not a mere key derivation function. A key stretching function is technically a kind of key derivation function, but most key derivation functions are not key stretching functions. A key stretching function is intrinsically slow to reduce the possibility of brute force guessing, and includes a salt input to make precomputations useless when attacking many accounts. See How to securely hash passwords? for more explanations: hashing a password and deriving a key from a password are very similar cryptographic problems with basically the same solution.

SP800-108 and SP800-56A are families of ordinary (non-stretching) key derivation functions. They are not suitable here. I don't know what CAPI_KDF is but according to the Windows API documentation it doesn't take a salt or a difficulty parameter so it can't be a key stretching function.

PBKDF2 is a key stretching function. It's designed precisely for what you want to do. It has weaknesses, but that's compared to more modern key stretching functions. Specifically, PBKDF2 intrinsically requires a lot of computing power, but very little memory, so it can be executed more cheaply on GPU or ASIC (which an attacker would typically use) than on a CPU (which the legitimate server is using). Scrypt and Argon require a lot of RAM (comparatively) which can only be realistically available on the same kind of hardware that a typical server is using, so the attacker doesn't have an advantage in terms of computing power. So PBKDF2 is not the best choice if you have a choice. But you don't have a choice: you don't have access to bcrypt, scrypt or Argon2. (Note that “bcrypt” here is the algorithm, it's unrelated to “bcrypt” as in bcrypt.h in the Windows API.) So use PBKDF2.

PBKDF2 for hashing passwords (or deriving keys from passwords) is ok. It isn't ideal, but it's ok. All of your other options would be catastrophically wrong.

Generally you should only use the key obtained with PBKDF2 to wrap (encrypt) another key. This way, when the user updates her password, you only need to update this wrapped key.

If you're both authenticating the password and deriving a key from it, see Is it safe to split the output of PBKDF2?

Note that a key stretching function can't do miracles. If the password space is too small, it's realistic for an attacker to try them all. For example, at 1 attempt per second (which is on the high side), it only takes a few hours to break a 4-digit PIN (13.3 bits of entropy). A case-insensitive 4-letter password with random letters has 18.8 bits of entropy and would only last a few days without parallelization. You really should make the minimum length higher.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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