hashing passwords with pbkdf2 crypto does not work correctly

人走茶凉 提交于 2019-12-11 12:24:15

问题


Password security is not my strong suit. Please help me out.

I use node.js 4.2.3 express 4.13.3. I found some examples to hash and salt passwords with crypto's pbkdf2.

Here is my code.

var salt = crypto.randomBytes(10).toString('base64');
console.log("salt  >  "+salt);
crypto.pbkdf2(pass, salt , 10000, 150, 'sha512',function(err, derivedKey) {
    pass = derivedKey.toString('hex');
});

The final derivedKey does not include the salt. What am I missing? Should I join the two strings manually before saving?

Why some examples use base64 and others hex? To get different string lenghts? What is the default, so I can use it?

Why not to use basic64 in both salt and hashed password?

Is the final derivedKey string UTF8? Or this has to do only with the database it gets saved? My database is in UTF8.

Thanks


回答1:


Yes, store the salt yourself, separately, unencrypted. Make sure it's randomly generated.

More importantly, you're crippling your PBKDF2 encryption by asking for 150 bytes (bytes per nodejs.org) of key length - SHA512 is a fantastic choice, but it only provides 64 bytes of native output. To get 10,000 iterations of 150 bytes of output, PBKDF2/RFC2898 is going to execute 30,000 times, while an offline attacker will only need to run 10,000 iterations and match the first 64 bytes (if the first 64 match, then the rest will too); you gave them a 3:1 advantage for free!

Instead, if you're happy with the work factor, you should use 30,000 iterations of 64 bytes of output - you'll spend the same amount of time, no difference, but the attacker now has to do 30,000 iterations too, so you took away their 3:1 advantage!

When you pass the salt to the PBKDF2 function, if you can, just pass in the pure binary. Also, the node.js docs say - reasonably "It is recommended that the salts are random and their lengths are greater than 16 bytes." This means binary 16 bytes, before the base64 or hex or whatever conversion if you want one.

You can save both salt and derivedkey as BINARY of the correct length for the most efficient storage (then you don't have to worry about UTF-x vs. ASCII), or you can convert one or both to BASE64 or hexadecimal, and then convert back to binary as required. Base64 vs hex vs binary is irrelevant as long as the conversions are reconverted as needed.

I'd also make the number of iterations a stored field, so you can easily increase it in the years to come, and include a field for the "version" of password hashing used, so you can easily change your algorithm in the years to come if need be as well.




回答2:


Encryption works with data, not strings, this includes the encryption key. PBKDF2 produces a data key, which can be easily converted to a string, this conversion is necessary because many data bytes have no corresponding print character or unicode code point. Many scripting languages do not handle data well so the data is many times converted to Base64 or hexadecimal (hex).

You can use Base64 or hexadecimal for the salt and hashed password, just be consistent on all uses.

The salt and iteration count need to be the same for creating an checking, you will need to combine them or save them separately.

Your code is converting the derived key to hexadecimal, that is fine and base64 would also be fine. Again this is necessary because not all data bytes are UTF-8.



来源:https://stackoverflow.com/questions/34459088/hashing-passwords-with-pbkdf2-crypto-does-not-work-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!