I am using the following methods to create a salted and hashed password from the crypto lib in nodejs:
crypto.randomBytes(size, [callback])
crypto.pbkdf2(password, salt, iterations, keylen, callback)
For the randomBytes call (creating the SALT) what size should I use? I have heard 128-bit salts, maybe up to 256-bit. It looks like this function uses a size in bytes so can I assume a size of 32 (256 bits) is sufficient?
For the pbkdf2 call, what is a good number of iterations and what is a good length for the key (keylen)?
Also, for storage I have seen examples of storing the salt, length, iterations and derviedkey in the same column. I am using an example which separates the 4 by ::
, i.e.:
salt::derivedKey::keyLength::iterations
Doing this, I can then separate on ::
to get the 4 values, so I can generate a derived key based on a provided password to see if it matches. Is this the correct way to store this? Or should I be a little more "deceptive" in combining these values?
1. Random bytes size:
Salts should be at least the same size as your hash function, so for sha256
you should use at least 32 bytes. Node.js Crypto's pbkdf2
uses SHA1
, so 20 bytes should be the minimum. However, the least you should use is 64 bits (8 bytes), as explained in #3. (Source: https://crackstation.net/hashing-security.htm).
2. PBKDF2 number of iterations:
See this question for a great discussion. I took from it that 10.000 range is sufficient without impact performance, but this is hardware/performance dependant.
3. PBKDF2 length:
See this other discussion about key lengths. The parameter is again the hashing function used, in your case SHA-1, so 20 bytes is the correct value. Since PBKDF2's Standard recommends salts of at least 64 bits, it's a waste to generate keys smaller than your input, so use at least 8 bytes. Do not use output length of greater than 20, as it provides no additional security, but doubles computation time for each multiple of 20.
4. How to store variables:
Discussed in all the links above (especially the first), salts should be saved along passwords (but never reused elsewhere), usually by appending it first in the resulting string (salt:hash), or in another database column.
As far as other variables, their knowledge is not critical for breaching security (as stated in Kerckhoffs's Principle, so you could parametrize it safely anywhere. Your way of doing it by separating them with "::" is fine, but you are saving extra information. Crackstation's codes only save "algorithm:iterations:salt:hash"
, so in your case, "salt::derivedKey::iterations"
is all you need.