Node.js password hashing bcrypt alternative using crypto
You can hash using pbkdf2 from the crypto library:
crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)
Sample implementation:
const crypto = require('crypto');
crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...aa39b34'
});
here goes the reference: https://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback
It uses HMAC digest algorithm such as sha512 to derive a key of given length from the given password, salt and iterations. Pbkdf2 has similar slowness features like bcrypt. With PBKDF2, bcrypt, or scrypt, the attacker can only make a few thousand guesses per second (or less, depending on the configuration).
bcrypt will be more secure than crypto, simply because it's slower. However, here are some password functions I wrote in coffeescript using crypto (I join the create_password
parts with a '$', you'll see that split in check_password
):
create_password = function(passwd, method, salt) {
var hmac;
method || (method = "sha1");
salt || (salt = crypto.randomBytes(6).toString('base64'));
hmac = crypto.createHmac(method, salt);
hmac.end(passwd);
return {
hash: hmac.read().toString('hex'),
salt: salt,
method: method
};
};
check_password = function(hashed, passwd) {
var hash, hashp, method, salt, _ref;
_ref = hashed.split("$"), method = _ref[0], salt = _ref[1], hashp = _ref[2];
hash = create_password(passwd, method, salt).hash;
return hash === hashp;
};
Example usage:
passwd = "SOME STRING HERE"
hash_parts = create_password(passwd)
hashed = pwd_parts.method + "$" + pwd_parts.salt + "$" + pwd_parts.hash
check_password(hashed, passwd)
As of 24th April 2020 There is a nice built in way of hashing passwords using scrypt
in the crypto
module. Its very secure since it utilizes a salt for hashing the password and its based off scrypt
// built right into nodejs
const crypto = require("crypto");
// salt - any random string here (ideally should be above 16 bytes)
const salt = "EoAZAJtVDdzPZmOxpx0EnqLmREYUfq";
function getHash() {
return crypto.scryptSync("your-password-here", salt, 32).toString("hex");
}
Note: i used 32 characters in length but you can specify your desired length