60

I am currently using the following for hashing passwords:

var pass_shasum = crypto.createHash('sha256').update(req.body.password).digest('hex');

Could you please suggest improvements to make the project safer?

3

10 Answers 10

107

I use the follwing code to salt and hash passwords.

var bcrypt = require('bcrypt');

exports.cryptPassword = function(password, callback) {
   bcrypt.genSalt(10, function(err, salt) {
    if (err) 
      return callback(err);

    bcrypt.hash(password, salt, function(err, hash) {
      return callback(err, hash);
    });
  });
};

exports.comparePassword = function(plainPass, hashword, callback) {
   bcrypt.compare(plainPass, hashword, function(err, isPasswordMatch) {   
       return err == null ?
           callback(null, isPasswordMatch) :
           callback(err);
   });
};
Sign up to request clarification or add additional context in comments.

4 Comments

Don't use else after return, it just dont make sense. Cheers!
Could you add a link to the bcrypt library which you are using (github if possible)? Thanks.
@Tadej it was so long ago, but I suppose it's: npmjs.com/package/bcrypt
There are two modules bcrypt and bcryptjs for this purpose, If someone can tell more about these two that would be nice.
7

bcrypt also can be called synchronously. Sample Coffeescript:

bcrypt = require('bcrypt')

encryptionUtil = 
    encryptPassword: (password, salt) ->
        salt ?= bcrypt.genSaltSync()
        encryptedPassword = bcrypt.hashSync(password, salt)
        {salt, encryptedPassword}

    comparePassword: (password, salt, encryptedPasswordToCompareTo) ->
        {encryptedPassword} = @encryptPassword(password, salt)
        encryptedPassword == encryptedPasswordToCompareTo

module.exports = encryptionUtil

Comments

6

bcrypt with typescript

npm i bcrypt
npm i -D @types/bcrypt
 import * as bcrypt from 'bcrypt';

export const Encrypt = {

    cryptPassword: (password: string) =>
        bcrypt.genSalt(10)
        .then((salt => bcrypt.hash(password, salt)))
        .then(hash => hash),
    
        comparePassword: (password: string, hashPassword: string) =>
            bcrypt.compare(password, hashPassword)
            .then(resp => resp)
    
    }

Exemple: Encrypt

const myEncryptPassword = await Encrypt.cryptPassword(password);

Exemple: Compare

const myBoolean = await Encrypt.comparePassword(password, passwordHash);

Comments

4

Also there is bcrypt-nodejs module for node. https://github.com/shaneGirish/bcrypt-nodejs.

Previously I used already mentioned here bcrypt module, but fall into problems on win7 x64. On the other hand bcrypt-nodejs is pure JS implementation of bcrypt and does not have any dependencies at all.

1 Comment

Would be nice but this is not maintained anymore.
1

You can use the bcrypt-js package for encrypting the password.

  1. Try npm i bcryptjs
  2. var bcrypt = require('bcryptjs') in top.
  3. To hash a password:
bcrypt.genSalt(10, function(err, salt) {
    bcrypt.hash("B4c0/\/", salt, function(err, hash) {
        // Store hash in your password DB.
    });
});
  1. To check your password,
// Load hash from your password DB.
bcrypt.compare("B4c0/\/", hash, function(err, res) {
    // res === true
});

You can visit https://www.npmjs.com/package/bcryptjs for more information on bcryptjs.

Comments

1

Try using Bcrypt, it secures the password using hashing.

bcrypt.hash(req.body.password, salt, (err, encrypted) => {
    user.password = encrypted
    next()
})

Where salt is the cost value which specifies the strength of hashing. While logging in, compare the password using bcrypt.compare method:

 bcrypt.compare(password, user.password, (err, same) => {
      if (same) {
           req.session.userId = user._id
           res.redirect('/bloglist')
      } else {
           res.end('pass wrong')
      }
 })

For more info, refer to this blog: https://medium.com/@nitinmanocha16/bcrypt-and-nodejs-e00a0d1df91f

Comments

1

Bcrypt isn't a bad choice, but there are a few gotchas:

  1. It will truncate on NUL bytes.
  2. It will truncate after 72 characters. If you're using passphrases, this might weaken your password unexpectedly.

As of October 2019, Argon2id is the optimal choice.

The preferred way of interfacing with Argon2id is through libsodium (a cryptography library that provides a lot of features). There are several bindings to choose from, but the easiest is probably sodium-plus.

const SodiumPlus = require('sodium-plus').SodiumPlus;
let sodium;
(async function(){
    if (!sodium) sodium = await SodiumPlus.auto(); // Autoload the backend

    let password = 'Your example password goes here. Provided by the user.';

    // Hashing...
    let hash = await sodium.crypto_pwhash_str(
        password,
        sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
        sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
    );
    // You can safely store {hash} in a database.

    // Checking that a stored hash is still up to snuff...
    let stale = await sodium.crypto_pwhash_str_needs_rehash(
        hash,
        sodium.CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE,
        sodium.CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE
    );
    if (stale) {
        // Rehash password, update database
    }

    // Password verification
    let valid = await sodium.crypto_pwhash_str_verify(password, hash);
    if (valid) {
        // Proceed...
    }
})();

The documentation for sodium-plus on Github includes password hashing and storage.

2 Comments

This answer needs upvotes!
Another gotcha is that bcrypt doesn't always work depending on server configuration. See this issue, which is still happening: github.com/kelektiv/node.bcrypt.js/issues/998 It's a crucial issue on shared hosting where you don't have root access to try the various fixes, such as rebuilding bcrypt from source, that are claimed to work.
0

For TypeScript you can use:

import { pbkdf2 } from "crypto";

export async function password2key(password: string): Promise<string> {
    return new Promise<string>( (resolve, reject) => {
        pbkdf2(password, config.passwordSalt, 10000, 64, 'sha512', (err, key) => {
            if (err) reject(err);
            else resolve(key.toString('base64'));
          });
    })
}

Comments

0
const bcrypt = require("bcrypt")

userSchema.pre("save", async function (next) {
    const salt = await bcrypt.genSalt(10);
    this.password = await bcrypt.hash(this.password, salt)
    next()
})

Comments

0

A simple solution is to use these function :

For typescript

import * as bcrypt from 'bcrypt';

const cryptPassword = (plaintextPassword: string) => {
    const salt = bcrypt.genSaltSync(10);
    return bcrypt.hashSync(plaintextPassword, salt);
}

const comparePassword = (plaintextPassword: string, hashword: string) => {
    return bcrypt.compareSync(plaintextPassword, hashword);
}

export {
    cryptPassword,
    comparePassword
};

Using js

var bcrypt = require('bcrypt');

const cryptPassword = (plaintextPassword) => {
    const salt = bcrypt.genSaltSync(10);
    return bcrypt.hashSync(plaintextPassword, salt);
}

const comparePassword = (plaintextPassword, hashword) => {
    return bcrypt.compareSync(plaintextPassword, hashword);
}

export {
    cryptPassword,
    comparePassword
};

Thanks to https://stackoverflow.com/a/14015883/22469248

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.