Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cryptography best practices for password storage in Node

I'm looking for a straightforward, secure, solution for storing a user's password using Node. I'm a cryptography novice, but have been trying to piece a solution together from researching online. I'm looking for validation that what I came up with is a solid solution for a web app with basic (not a bank, hospital, etc) security needs. Here it is:

var crypto = require('crypto');
var SALT_LENGTH = 64;
var KEY_LENGTH = 64;
var ITERATIONS = 1000;

function createHashedPassword(plainTextPassword, cb) {
    crypto.randomBytes(SALT_LENGTH, function (err, salt) {
        console.time('password-hash');
        crypto.pbkdf2(plainTextPassword, salt, ITERATIONS, KEY_LENGTH, function (err, derivedKey) {
            console.timeEnd('password-hash');
            return cb(null, {derivedKey: derivedKey, salt: salt, iterations: ITERATIONS});
        });
    });
};

...and here are the choices I made that brought me to this point:

What hashing algorithm to use?

Based on this widely referenced article, it looks like the leading contenders are PBKDF2, bcrypt, and scrypt. I chose PBKDF2 because it has built in support in Node.

What salt size to use?

This stack overflow answer seemed to be the most straightforward answer I could find. I'm still not very clear on why 64 bytes is the right salt size though. When I google around, I get other stack exchange answers like this, but I'm not sure it applies to the Node algorithm? Totally confused here, an explanation aimed at a novice using this Node function would be awesome.

What key length to use?

Once again, I largely based my choice off the same answer as above, but I'm just as foggy on the basics of 'why'. The answer says that 'it's a waste to generate keys smaller than your input, so use at least 64 bytes'. Huh? Once again, a practical explanation would be helpful.

How many iterations to use?

For this question, I based my choice off this stack exchange answer. I don't understand much of it, but I did get that the algorithm is supposed to take approximately 8ms. So, as you can see I put timers on the function, and I adjusted my iterations to get it in that ballpark on my machine.

Thanks!

like image 517
markdb314 Avatar asked Oct 22 '14 23:10

markdb314


People also ask

Which cryptographic algorithm is best used for secure storage of passwords?

To protect passwords, experts suggest using a strong and slow hashing algorithm like Argon2 or Bcrypt, combined with salt (or even better, with salt and pepper). (Basically, avoid faster algorithms for this usage.) To verify file signatures and certificates, SHA-256 is among your best hashing algorithm choices.

Is bcrypt better than SHA-256?

The technology in the Bcrypt algorithm and process limits attacks and makes it harder for attackers to compromise passwords. Bcrypt was not designed for encrypting large amounts of data. It is best implemented for passwords, however SHA-256 is better for large amounts of data because it is less costly and faster.


2 Answers

The NPM package credential handles all of these

You can see the author's write up on it in the book Programming Javascript Applications

like image 88
Alex Hill Avatar answered Oct 07 '22 11:10

Alex Hill


I would strongly recommend using BCrypt. There are lots of advantages to the algorithm, and most implementations handle all of these questions for you.

As described in this answer:

Bcrypt has the best kind of repute that can be achieved for a cryptographic algorithm: it has been around for quite some time, used quite widely, "attracted attention", and yet remains unbroken to date.

I've written up a detailed article about how to implement BCrypt in node/express as well as other frameworks here: http://davismj.me/blog/bcrypt

like image 3
Matthew James Davis Avatar answered Oct 07 '22 12:10

Matthew James Davis