crypto.pbkdf2 is asynchronous, how do I treat it as synchronous?
Asked Answered
M

2

7

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.

Mosby answered 9/1, 2013 at 13:37 Comment(0)
C
6

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.

Castiron answered 9/1, 2013 at 13:59 Comment(4)
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.Mosby
@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 for more info.Castiron
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.Mosby
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".Castiron
E
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.

Entangle answered 25/3, 2013 at 4:23 Comment(3)
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.Mosby
fifth argument is digest. crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)Craver
It's also nice to add a code example alongside your response.Midlands
C
6

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.

Castiron answered 9/1, 2013 at 13:59 Comment(4)
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.Mosby
@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 for more info.Castiron
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.Mosby
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".Castiron

© 2022 - 2024 — McMap. All rights reserved.