27

I want to create a salt-hash using node.js crypto lib without having to parse any hardcoded data.

What do I mean with hardcoded?

var salt, hardcodedString = "8397dhdjhjh";
crypto.createHmac('sha512', hardcodedString).update(salt).digest("base64");

Isn't there any other way how I can create a random string without using raw javascript, random functions or hardcoding something?

Regards

UPDATE

var Crypto = require('crypto')
    , mongoose = require('mongoose');

module.exports = mongoose.model('User', new mongoose.Schema({
    username: {
        type: String
        , required: true
        , index: { unique: true, sparse: true }
        , set: toLower
    },
    email: {
        type: String
        , required: true
        , index: { unique: true, sparse: true }
        , set: toLower
    },
    salt: {
        type: String
        , set: generateSalt
    },
    password: {
        type: String
        , set: encodePassword
    }
}),'Users');

function toLower(string) {
    return string.toLowerCase();
}

function generateSalt() {
    //return Math.round((new Date().valueOf() * Math.random())) + '';
    Crypto.randomBytes('256', function(err, buf) {
        if (err) throw err;
        return buf;
    });
    // return Crypto.randomBytes('256'); // fails to
}

function encodePassword(password) {
    return password;
    // TODO: setter has no access to this.salt
    //return Crypto.createHmac('sha512', salt).update(password).digest("base64");
}

function authenticate(plainPassword) {
    return encodePassword(plainPassword) === this.password;
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
dev.pus
  • 7,919
  • 13
  • 37
  • 51
  • 2
    btw plain HMAC is no secure password hash. `crypto.pbkdf2` with >50000 iterations is a decent choice. – CodesInChaos Jul 17 '12 at 11:41
  • 5
    ^- That's called ['stretching'](http://throwingfire.com/storing-passwords-securely/) for those who don't know. – Justin Beaudry Nov 14 '13 at 03:16
  • Very good link. It's good to find a post that contains a whole lot of info about the subject and with a good explanation. – Gaston Sanchez Dec 10 '13 at 23:08
  • Why would you do 'stretching' by putting an actual load on the processor, instead of just delaying the response the chosen amount of time? – Mikael Grön Aug 18 '15 at 19:32
  • 1
    @MikaelGrön The goal is to slow down an attacker who computes hashes on their own computer (typically on the GPU). That it slows down your own server is an unfortunate side-effect. – CodesInChaos Sep 27 '15 at 11:28

2 Answers2

52

A quick look at the documentation turns up the crypto.randomBytes function.

var buf = crypto.randomBytes(16);

This returns a buffer containing raw bytes. If you want a string, you can use toString('base64') or toString('hex').

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Why are you quoting the number? And 256 bytes is a bit long for a salt, the 256 in my post is just quotes from the example. – CodesInChaos Jul 17 '12 at 11:39
  • Sry, changed to return Crypto.randomBytes(256);.. still no salt in the mongodb document. I will check if this is a mongoose problem – dev.pus Jul 17 '12 at 12:16
  • Ok, set isn't triggered automaticly only if there really is a value for the attribute. I changed set: generateSalt to default: generateSalt. This works now. However is there a way to encode your salt as hex or base64? – dev.pus Jul 17 '12 at 12:19
  • 27
    crypto.randomBytes(128).toString('base64'); – dak Sep 14 '12 at 14:25
1

You can do this by running on the node REPL

node
Welcome to Node.js v16.19.0.
Type ".help" for more information.
> crypto.randomBytes(16).toString('base64')
Arunabh Das
  • 13,212
  • 21
  • 86
  • 109