I am trying to figure out how to salt and hash a password in nodejs using the crypto module. I am able to create the hashed password doing this:
UserSchema.pre('save', function(next) {
var user = this;
var salt = crypto.randomBytes(128).toString('base64');
crypto.pbkdf2(user.password, salt, 10000, 512, function(err, derivedKey) {
user.password = derivedKey;
next();
});
});
However I am confused about how to later validate the password.
UserSchema.methods.validPassword = function(password) {
// need to salt and hash this password I think to compare
// how to I get the salt?
}
Storing plain text passwords is one of the worst habits of our time. Don't store plain text passwords, instead use passwords hashing. NodeJs JavaScript Hashing. Imagine a scenario where you store all the user passwords in plain text in your database, i.e., passwords are stored in the database without any modification.
One of the best ways to store passwords securely is to salt and hash them. Salting and hashing converts a plain password to a unique value that is difficult to reverse. The bcrypt library lets you hash and salt passwords in Node. js with very little effort.
A salt is a random string that makes the hash unpredictable. Bcrypt is a popular and trusted method for salt and hashing passwords. You have learned how to use bcrypt's NodeJS library to salt and hash a password before storing it in a database.
In whatever persistence mechanism (database) you're using, you would store the resulting hash alongside the salt and number of iterations, both of which would be plaintext. If each password uses different salt (which you should do), you must also save that information.
You would then compare the new plain text password, hash that using the same salt (and iterations), then compare the byte sequence with the stored one.
To generate the password (pseudo)
function hashPassword(password) {
var salt = crypto.randomBytes(128).toString('base64');
var iterations = 10000;
var hash = pbkdf2(password, salt, iterations);
return {
salt: salt,
hash: hash,
iterations: iterations
};
}
To validate password (pseudo)
function isPasswordCorrect(savedHash, savedSalt, savedIterations, passwordAttempt) {
return savedHash == pbkdf2(passwordAttempt, savedSalt, savedIterations);
}
Based on the nodejs documentation (http://nodejs.org/api/crypto.html), it doesn't look like there is a specific method that will validate a password for you. To validate it manually, you will need to compute the hash of the currently provided password and compare it to the stored one for equality. Basically, you will do the same thing with the challenge password that you did with the original, but use the salt stored in the database instead of generating a new one, and then compare the two hashes.
If you aren't too committed to using the built in crypto library, I might recommend using bcrypt instead. The two are about equal on the security front, but I think bcrypt has a more user-friendly interface. An example of how to use it (taken directly from the bcrypt docs on the page linked above) would be this:
Create a hash:
var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync("B4c0/\/", salt);
// Store hash in your password DB.
To check a password:
// Load hash from your password DB.
bcrypt.compareSync("B4c0/\/", hash); // true
bcrypt.compareSync("not_bacon", hash); // false
Edit to add:
Another advantage of bcrypt is that the output of the genSalt function contains both the hash and the salt in one string. This means that you can store just the single item in your database, instead of two. There is also a method provided that will generate a salt at the same time that the hashing occurs, so you don't have to worry about managing the salt at all.
Edit to update:
In response to the comment from Peter Lyons: you're 100% correct. I had assumed that the bcrypt module that I had recommended was a javascript implementation, and therefor using it asynchronously wouldn't really speed things up on node's single threaded model. It turns out that this is not the case; the bcrypt module uses native c++ code for it's computations and will run faster asynchronously. Peter Lyons is right, you should use the asynchronous version of the method first and only pick the synchronous one when necessary. The asynchronous method might be as slow as the synchronous one, but the synchronous one will always be slow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With