9

I'm actually using bcrypt module to hash and compare hashed passwords.

What i would like to do is to remove the bcrypt module and use the default crypto library both for hashing and comparing passwords.

Is this possible?

Will this be less safe than using node-bcrypt?

Do you have any example/tutorial/doc/link on how to do?

or example i'm doing like this actually:

bcrypt.hash(string,secret_key)
bcrypt.compare(string,string,secret_key);

i just would like to replicate this with crypto if possible:

crypto.hash(string,secret_key)
    crypto.compare(string,string,secret_key);

4 Answers 4

9

You can hash using pbkdf2 from the crypto library:

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

Sample implementation:

const crypto = require('crypto');
crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err, derivedKey) => {
  if (err) throw err;
  console.log(derivedKey.toString('hex'));  // '3745e48...aa39b34'
});

here goes the reference: https://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback

It uses HMAC digest algorithm such as sha512 to derive a key of given length from the given password, salt and iterations. Pbkdf2 has similar slowness features like bcrypt. With PBKDF2, bcrypt, or scrypt, the attacker can only make a few thousand guesses per second (or less, depending on the configuration).

Sign up to request clarification or add additional context in comments.

5 Comments

Note that attackers using oclHashcat with GPU's or similar can make many more guesses per second than you, unless you really ramp up the iterations. For example, a single PC with 8x AMD R9 290Xstock core clock can make more or less 1.3 million PBKDF2-HMAC-SHA-1(password,salt,8192,20) tests per second, i.e. 3.4E12 or 2^41 guesses every 30 days. You have to up your iteration count (or BCrypt work factor) to crimp their style more.
@Anti-weakpasswords Yes, cpu and gpu speeds are always upgrading, that's why you have configurable iterations in pbkdf2, so you can always keep the balance
@Masum, note also that if you can use PBKDF2-HMAC-SHA-384 or PBKDF2-HMAC-SHA-512 on a 64-bit system, you can reduce the margin of advantage that the GPU based attacker has, as current generation GPU's aren't nearly as good at the 64-bit operations required for SHA-384 and SHA-512 as they are at 32-bit operations.
How do I verify the password? I need to store the salt in the database explicitly, and then run the same thing over?
Have any of you been able to get this functioning on a Centos 5 system? I have this functioning locally but on my remote box it throws an error crypto.pbkdf2('secret', 'buf', 1028, 64, 'sha256', function(err, key) {...}); ^ TypeError: Bad parameter
3

bcrypt will be more secure than crypto, simply because it's slower. However, here are some password functions I wrote in coffeescript using crypto (I join the create_password parts with a '$', you'll see that split in check_password):

  create_password = function(passwd, method, salt) {
    var hmac;
    method || (method = "sha1");
    salt || (salt = crypto.randomBytes(6).toString('base64'));
    hmac = crypto.createHmac(method, salt);
    hmac.end(passwd);
    return {
      hash: hmac.read().toString('hex'),
      salt: salt,
      method: method
    };
  };

  check_password = function(hashed, passwd) {
    var hash, hashp, method, salt, _ref;
    _ref = hashed.split("$"), method = _ref[0], salt = _ref[1], hashp = _ref[2];
    hash = create_password(passwd, method, salt).hash;
    return hash === hashp;
  };

Example usage:

passwd = "SOME STRING HERE"
hash_parts = create_password(passwd)
hashed = pwd_parts.method + "$" + pwd_parts.salt + "$" + pwd_parts.hash
check_password(hashed, passwd)

2 Comments

Yeah, it was legacy stored that way, and my app didn't require anything super secure. Obviously configurable though!
+1 for the helpp, thanks man but i preferr the other suggestion above in my case is better :)
2

As of 24th April 2020 There is a nice built in way of hashing passwords using scrypt in the crypto module. Its very secure since it utilizes a salt for hashing the password and its based off scrypt

// built right into nodejs
const crypto = require("crypto");

// salt - any random string here (ideally should be above 16 bytes)
const salt = "EoAZAJtVDdzPZmOxpx0EnqLmREYUfq";
function getHash() {
  return crypto.scryptSync("your-password-here", salt, 32).toString("hex");
}

Note: i used 32 characters in length but you can specify your desired length

4 Comments

1- "crypto.scryptSync" is same with "crypto.pbkdf2Sync" ? ------------------------------------------------------------------ 2- "crypto.scryptSync" is better than "bcrypt" or "node.bcrypt.js" ? ---------------------------------------------------------- 3- Do we need to create and use static salt to use crypto.scryptSync ? is this safe ?
1. no they are both different algorithms. 2. yes it is based on the excellent 'scrypt' algorithm which is second only to argon and is generally better than the older bcrypt algorithm 3. The salt should be static (it cant be dynamic) since you will need the same salt to decode the hashed password (so it is recommended to make it strong) and also to make it secure (prefferably in an environment variable)
thank you very much. what is difference between "crypto.scryptSync" and "crypto.pbkdf2Sync" ? which is better ?
@Kiax They use different algorithms under the hood (scrypt, pbkdf2) but they are both equally good (django uses pbkdf2).
-2

An alternative the bcryptjs. The concept is the same as bcrypt but no dependencies and compatible to bcrypt.

https://github.com/dcodeIO/bcrypt.js

https://www.npmjs.com/package/bcryptjs

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.