6

I'm using pbkdf2 in node.js for hashing passwords.

My problem is that I'm responding to a request for authentication and I'm in the middle of authenticating if the passed credentials are correct. I'm presuming that pbkdf2 is async as it could potentially take a large amount of time (dependant on the size of the iterations). However moving the remaining authentication logic into a separate method to utilise the callback seems a tad ugly.

Is there a better approach than either using a timer or throwing all the consecutive authentication logic into a separate function? I know most will say that I should use the callback, but in my use case this just doesn't make sense. I cannot continue authentication until I have applied pbkdf2 to the passed password.

Kevin Hakanson
  • 41,386
  • 23
  • 126
  • 155
Metalskin
  • 3,998
  • 5
  • 37
  • 61

2 Answers2

8

According to the Node.js crypto docs, there is both an asynchronous and synchronous version of the PBKDF2 function.

crypto.pbkdf2(password, salt, iterations, keylen, callback)

Asynchronous PBKDF2 applies pseudorandom function HMAC-SHA1 to derive a key of given length from the given password, salt and iterations. The callback gets two arguments (err, derivedKey).

crypto.pbkdf2Sync(password, salt, iterations, keylen)

Synchronous PBKDF2 function. Returns derivedKey or throws error.

Kevin Hakanson
  • 41,386
  • 23
  • 126
  • 155
  • 1
    Thanks Kevin, I'm not sure why I didn't see that last year. If it works then it's a better answer as it's what I actually wanted. When I get a chance I'll revisit the code and test. – Metalskin May 07 '14 at 22:59
  • fifth argument is digest. crypto.pbkdf2Sync(password, salt, iterations, keylen, digest) – V-SHY Oct 02 '18 at 12:28
5

I can see two solutions for your problem.

First one is to use some library to wrap asynchronous calls. You may try node-sync or node-promise. node-sync is better suited for what you want.

Second solution is to use bcrypt instead of crypto:

var bcrypt = require('bcrypt');
var salt = bcrypt.genSaltSync(10);
var hash = bcrypt.hashSync(password, salt);

bcrypt is a special library for password hashing in node. It's more secure then build-in crypto module and provides some useful methods like hashSync and compareSync.

Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
  • Am I right in presuming that the bcrypt is based on blowfish (as per the wikipedia link from the node.bcrypt.js project)? I was using pbkdf2 with a salt larger than 128 bits and with 10000 iterations, which afaict is NIST approved, while the blowfish bcrypt is not (refer wikipedia artical). I'm just curious on your comment that bcrypt is more secure. For my purposes it's most prob. not that critical, but I would like to use the most secure approach. – Metalskin Jan 09 '13 at 22:33
  • 1
    @Metalskin, I investigated a little bit more. `Bcrypt` is stronger on shorter pathphrases, but it starts loosing to `pbkdf2` on pathfrases longer then 55 characters. But they both are safe enough, so there is no real difference. See [this answer](http://stackoverflow.com/questions/4433216/password-encryption-pbkdf2-using-sha512-x-1000-vs-bcrypt) for more info. – Leonid Beschastny Jan 09 '13 at 23:02
  • Thanks that link was really helpful, I don't think I will be going over 55 characters so it should be okay to use bcrypt. Looks like scrypt would be better but I couldn't find any active projects for node.js. – Metalskin Jan 09 '13 at 23:14
  • 2
    When I said that there is no real difference, I meant that it's practically impossible to unhash pbkdf2-hashed string. Bcrypt is ten times stronger for average-sized passphrases (8 characters). But "ten times impossible" is just an "impossible". – Leonid Beschastny Jan 09 '13 at 23:16