vignesh vignesh - 10 months ago 42
Node.js Question

NodeJS pbkdf2Sync password hasing portability from v0.12.7 to v6.9.1

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);


* 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:

The express commit made in git:

Crypto documentation:

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.

Answer Source

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');