Reputation: 1860
I have been working on porting an application written from node v0.12.7 to node v6.9.1.
We are using MEAN stack with all of them upgraded to their latest versions.
We have been able to upgrade everything except for one problem. We used pbkdf2Sync method (comes inbuilt with express) for hashing passwords like so:
/**
* Hook a pre save method to hash the password
*/
UserSchema.pre('save', function(next) {
if (this.password && this.password.length > 6) {
this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64');
this.password = this.hashPassword(this.password);
}
next();
});
/**
* Create instance method for hashing a password
*/
UserSchema.methods.hashPassword = function(password) {
if (this.salt && password) {
return crypto.pbkdf2Sync(password, this.salt, 10000, 64).toString('base64');
} else {
return password;
}
};
In the latest versions, they have changed the encoding to utf8 and also changed the pbkdf2Sync to include a mandatory digest. I am not sure what else they have changed.
The problem:
The passwords hashed and stored in the mongo database using earlier version of node does not match with the password generated by hashPassword function after version upgrade.
I have tried:
1) Specifying encoding string
2) Using buffers
3) Adding digest option as parameter
And I dont get the same hashed password with any of these.
I tried changing the hashPassword function with many combinations. One of the tries I made was this, but does not work.
UserSchema.methods.hashPassword = function (password) {
if (this.salt && password) {
return crypto.pbkdf2Sync(password, new Buffer(this.salt, 'base64').toString('binary'), 10000, 64, 'SHA1').toString('base64');
} else {
return password;
}
};
A test case:
Password to hash: ramco@123
Salt: d\u001e'��\u0001\u0004\u0012)aq�**G\u000f
Result I am supposed to get: kG6uCjSk87I7PrXMko+nS8Mz/78LMilXDMJZI0mzBgi75mBpi8hIkh3+B8CqpuYZdvvs5HWjcNthhhnUA89sCw==
But I get some other string from the hashPassword function.
I referred:
The NodeJS commit made in git: https://github.com/nodejs/node/commit/b010c8716498dca398e61c388859fea92296feb3
The express commit made in git: https://github.com/meanjs/mean/commit/61f1a22c91ac15f06143ace6e540b334fa9e3bd6
Crypto documentation: https://nodejs.org/api/crypto.html
How to store crypto pbkdf2 in mongoDB?
And lot of other sites and forums but did not help me. Kindly help me if you can.
Thanks in advance.
Upvotes: 4
Views: 412
Reputation: 203514
Looks like older versions of Node used SHA-1 as digest. Also, you should pass in the salt as a binary buffer (I'm using the supplied salt string from your example, if you have stored the salt as Base64-encoded binary you can probably leave the base64
encoding that you're using as-is and only explicitly set the correct digest).
The following yields the expected result:
const crypto = require('crypto');
let password = 'ramco@123';
let salt = `d\u001e'��\u0001\u0004\u0012)aq�**G\u000f`;
let x = crypto.pbkdf2Sync(password, new Buffer(salt, 'binary'), 10000, 64, 'sha1').toString('base64');
console.log(x);
Upvotes: 6