488

I have a string that I want to hash. What's the easiest way to generate the hash in node.js?

The hash is for versioning, not security.

Francisco
  • 10,918
  • 6
  • 34
  • 45
Harry
  • 52,711
  • 71
  • 177
  • 261

14 Answers14

952

If you just want to md5 hash a simple string I found this works for me.

var crypto = require('crypto');
var name = 'braitsch';
var hash = crypto.createHash('md5').update(name).digest('hex');
console.log(hash); // 9b74c9897bac770ffc029102a200c5de
braitsch
  • 14,906
  • 5
  • 42
  • 37
  • 242
    Woot woot, if you do `require('crypto').createHash('md5').update(STRING_TO_BE_HASHED).digest("hex")` you got a one-liner. Cheers mate! – balupton Aug 10 '12 at 10:26
  • 3
    Was getting some issues using `.update` multiple times (https://github.com/joyent/node/issues/749) when trying to use `timbooo`'s solution, using the one-liner fixed it (because the hash object is recreated every time). – Max Jul 04 '13 at 07:34
  • 1
    Any way to change the length of the string? Not only 32 characters, 64 or 128 or a different number. – Mikel Sep 02 '15 at 11:17
  • 1
    @Mikel try if there are other hash algorithms that suit your needs, md5 is always 32 characters. – Ties Jul 28 '16 at 12:11
  • 1
    If I have lots of strings to hash, it is less efficient to keep calling crypto.createHash instead of somehow re-using the result? – Michael Mar 28 '19 at 03:23
  • 1
    isnt md5 deprecated and insecure? – RedGuy11 Aug 23 '21 at 02:31
  • 5
    @RedGuy11 It's not deprecated at all. It IS very insecure for hashing passwords but there are many other use cases for hashing other than passwords. For example, creating MD5 checksums for files. – KyleFarris Nov 03 '21 at 20:26
  • 2
    @balupton one liners come with a huge cost – Curcuma_ Mar 23 '22 at 11:46
  • How do I convert back the hash to the string? :( – Bruno Peixoto Apr 28 '22 at 21:44
  • @BrunoHenriquePeixoto you can't, that's why it's called a hash, instead of an encrypted string. Information about the original content has been lost, but we have saved space and produced a short checksum that *represents* the (potentially very large) content. – ciscoheat Aug 10 '22 at 09:26
267

Take a look at crypto.createHash(algorithm)

var filename = process.argv[2];
var crypto = require('crypto');
var fs = require('fs');

var md5sum = crypto.createHash('md5');

var s = fs.ReadStream(filename);
s.on('data', function(d) {
  md5sum.update(d);
});

s.on('end', function() {
  var d = md5sum.digest('hex');
  console.log(d + '  ' + filename);
});
nickf
  • 537,072
  • 198
  • 649
  • 721
dertkw
  • 7,798
  • 5
  • 37
  • 45
  • What is the s.on() function doing? Is it registering the md5sum.update(d) function to execute every time there is data being read from the ReadStream? – DucRP Jul 14 '15 at 17:01
  • @YoniDor Did you try [fs.readsync](https://nodejs.org/api/fs.html#fs_fs_readsync_fd_buffer_offset_length_position)? — Digesting in a classic while-loop, then be sure that it's done... ➝ http://stackoverflow.com/a/21219407/444255 – Frank N Feb 15 '16 at 16:19
  • 21
    OP wants to hash a string, not a file. – blimpse Feb 07 '18 at 17:14
88

Node's crypto module API is still unstable.

As of version 4.0.0, the native Crypto module is not unstable anymore. From the official documentation:

Crypto

Stability: 2 - Stable

The API has proven satisfactory. Compatibility with the npm ecosystem is a high priority, and will not be broken unless absolutely necessary.

So, it should be considered safe to use the native implementation, without external dependencies.

For reference, the modules mentioned bellow were suggested as alternative solutions when the Crypto module was still unstable.


You could also use one of the modules sha1 or md5 which both do the job.

$ npm install sha1

and then

var sha1 = require('sha1');

var hash = sha1("my message");

console.log(hash); // 104ab42f1193c336aa2cf08a2c946d5c6fd0fcdb

or

$ npm install md5

and then

var md5 = require('md5');

var hash = md5("my message");

console.log(hash); // 8ba6c19dc1def5702ff5acbf2aeea5aa

(MD5 is insecure but often used by services like Gravatar.)

The API of these modules won't change!

pvorb
  • 7,157
  • 7
  • 47
  • 74
  • 10
    I think it's much easier and efficient to utilize Crypto rather than bringing in a whole new module. – Valjas Jun 05 '13 at 17:04
  • 6
    From the current Node.js docs: _"Stability: 2 - Unstable; API changes are being discussed for future versions. Breaking changes will be minimized."_ The API of my module won't change. When I initially wrote the module, there was **no** `crypto` module built into the platform. Another advantage is that you can use my module on the server as well as the client side. But it is totally up to you, what library you use. – pvorb Jun 05 '13 at 17:51
  • 7
    The build in Crypto hashes kept giving me the 'hash update failed' BS. Finally I moved to the MD5 module and it worked just fine. Also easier to call (slightly). Thank you. – GJK Aug 31 '13 at 14:08
  • 2
    +1 for an option that stays away from the (2) - Unstable nature of the Crypto API! – Geek Stocks Oct 05 '13 at 02:50
  • 1
    I've fixed a weird sha1 problem on node 0.11.x on my Windows machine by swapping the standard crypto use for this module. – Bartvds Mar 26 '14 at 22:28
  • it's marked as stable now, should probably delete this answer – Robert Levy Jun 11 '14 at 15:50
  • @RobertLevy Where's that info from? [The official docs still say it's unstable](http://nodejs.org/api/crypto.html) – pvorb Jun 11 '14 at 16:17
  • In the v0.6.18 docs linked in @timbooo's answer, it's marked as Stable (3). The current (v0.10.29) docs show Unstable (2). – Jake Cobb Jul 16 '14 at 01:09
  • @JakeCobb Yes. I added that reason after writing the initial answer. – pvorb Aug 11 '14 at 18:03
  • The `require('MD5')` module declares it being insecure. Can we still have confidence in using it? – Con Antonakos May 21 '15 at 17:22
  • 1
    Do you mean the statement "Warning: MD5 is an insecure hashing algorithm. Don't use it unless you know what you are doing!" in the project README? This is about MD5 being an insecure hashing algorithm (see [the security section of the Wikipedia article for MD5](https://en.wikipedia.org/wiki/MD5#Security)). The library is compliant to the standard though and very stable. – pvorb May 21 '15 at 19:55
  • I removed that statement since it is misleading about the quality of the software. – pvorb May 21 '15 at 19:58
  • 1
    "MD5" is deprecated, you have to use "md5" (lowercase) instead. Example: `$ npm install md5` – Vítor Oliveira Aug 24 '16 at 05:10
  • @vitor_gaudencio_oliveira Thanks for the note. I updated the answer. – pvorb Aug 24 '16 at 21:52
30
sha256("string or binary");

I experienced issue with other answer. I advice you to set encoding argument to binary to use the byte string and prevent different hash between Javascript (NodeJS) and other langage/service like Python, PHP, Github...

If you don't use this code, you can get a different hash between NodeJS and Python...

How to get the same hash that Python, PHP, Perl, Github (and prevent an issue) :

NodeJS is hashing the UTF-8 representation of the string. Other languages (like Python, PHP or PERL...) are hashing the byte string.

We can add binary argument to use the byte string.

Code :

const crypto = require("crypto");

function sha256(data) {
    return crypto.createHash("sha256").update(data, "binary").digest("base64");
    //                                               ------  binary: hash the byte string
}

sha256("string or binary");

Documentation:

  • crypto.createHash(algorithm[, options]): The algorithm is dependent on the available algorithms supported by the version of OpenSSL on the platform.
  • hash.digest([encoding]): The encoding can be 'hex', 'latin1' or 'base64'. (base 64 is less longer).

You can get the issue with : sha256("\xac"), "\xd1", "\xb9", "\xe2", "\xbb", "\x93", etc...

  • Other languages (like PHP, Python, Perl...) and my solution with .update(data, "binary") :

      sha1("\xac") //39527c59247a39d18ad48b9947ea738396a3bc47
    
  • Nodejs by default (without binary) :

      sha1("\xac") //f50eb35d94f1d75480496e54f4b4a472a9148752
    
Community
  • 1
  • 1
user2226755
  • 12,494
  • 5
  • 50
  • 73
30

Simple One Liners:

If you want UTF8 text hash:

const hash = require('crypto').createHash('sha256').update('Hash me', 'utf8').digest('hex');

If you want to get the same hash with Python, PHP, Perl, Github:

const hash = require('crypto').createHash('sha256').update('Hash me', 'binary').digest('hex');

You can also replace 'sha256' with 'sha1', 'md5', 'sha256', 'sha512'

chickens
  • 19,976
  • 6
  • 58
  • 55
26

The crypto module makes this very easy.

Setup:

// import crypto from 'crypto';
const crypto = require('crypto');

const sha256 = x => crypto.createHash('sha256').update(x, 'utf8').digest('hex');

Usage:

sha256('Hello, world. ');
sdgfsdh
  • 33,689
  • 26
  • 132
  • 245
12

Here you can benchmark all supported hashes on your hardware, supported by your version of node.js. Some are cryptographic, and some is just for a checksum. Its calculating "Hello World" 1 million times for each algorithm. It may take around 1-15 seconds for each algorithm (Tested on the Standard Google Computing Engine with Node.js 4.2.2).

for(var i1=0;i1<crypto.getHashes().length;i1++){
  var Algh=crypto.getHashes()[i1];
  console.time(Algh);
  for(var i2=0;i2<1000000;i2++){
    crypto.createHash(Algh).update("Hello World").digest("hex");
  }
  console.timeEnd(Algh);  
}

Result:
DSA: 1992ms
DSA-SHA: 1960ms
DSA-SHA1: 2062ms
DSA-SHA1-old: 2124ms
RSA-MD4: 1893ms
RSA-MD5: 1982ms
RSA-MDC2: 2797ms
RSA-RIPEMD160: 2101ms
RSA-SHA: 1948ms
RSA-SHA1: 1908ms
RSA-SHA1-2: 2042ms
RSA-SHA224: 2176ms
RSA-SHA256: 2158ms
RSA-SHA384: 2290ms
RSA-SHA512: 2357ms
dsaEncryption: 1936ms
dsaWithSHA: 1910ms
dsaWithSHA1: 1926ms
dss1: 1928ms
ecdsa-with-SHA1: 1880ms
md4: 1833ms
md4WithRSAEncryption: 1925ms
md5: 1863ms
md5WithRSAEncryption: 1923ms
mdc2: 2729ms
mdc2WithRSA: 2890ms
ripemd: 2101ms
ripemd160: 2153ms
ripemd160WithRSA: 2210ms
rmd160: 2146ms
sha: 1929ms
sha1: 1880ms
sha1WithRSAEncryption: 1957ms
sha224: 2121ms
sha224WithRSAEncryption: 2290ms
sha256: 2134ms
sha256WithRSAEncryption: 2190ms
sha384: 2181ms
sha384WithRSAEncryption: 2343ms
sha512: 2371ms
sha512WithRSAEncryption: 2434ms
shaWithRSAEncryption: 1966ms
ssl2-md5: 1853ms
ssl3-md5: 1868ms
ssl3-sha1: 1971ms
whirlpool: 2578ms

user3077458
  • 131
  • 1
  • 4
4

I had to throw my 2 cents in hope this helps someone out.

For those using CommonJS

const crypto = require('crypto');
const secret = 'I love writing code, fixing things and building helpful tools';
const hash = crypto.createHmac('sha256', secret).digest('hex');

console.log('Hash successfully generated: ', hash);

For those using ES Modules

const { createHmac } = await import('crypto');
const secret = 'I love writing code, fixing things and building helpful tools';
const hash = createHmac('sha256', secret).digest('hex');

console.log('Hash successfully generated: ', hash);

Super simple! Happy Coding :)

0xe1λ7r
  • 1,957
  • 22
  • 31
1

I use blueimp-md5 which is "Compatible with server-side environments like Node.js, module loaders like RequireJS, Browserify or webpack and all web browsers."

Use it like this:

var md5 = require("blueimp-md5");

var myHashedString = createHash('GreensterRox');

createHash(myString){
    return md5(myString);
}

If passing hashed values around in the open it's always a good idea to salt them so that it is harder for people to recreate them:

createHash(myString){
    var salt = 'HnasBzbxH9';
    return md5(myString+salt);
}
GreensterRox
  • 6,432
  • 2
  • 27
  • 30
1
function md5(a) {
    var r = 0,
        c = "";
    return h(a);

    function h(t) {
        return u(l(m(t)))
    }

    function l(t) {
        return p(g(f(t), 8 * t.length))
    }

    function u(t) {
        for (var e, i = r ? "0123456789ABCDEF" : "0123456789abcdef", n = "", o = 0; o < t.length; o++)
            e = t.charCodeAt(o),
            n += i.charAt(e >>> 4 & 15) + i.charAt(15 & e);
        return n
    }

    function m(t) {
        for (var e, i, n = "", o = -1; ++o < t.length;)
            e = t.charCodeAt(o),
            i = o + 1 < t.length ? t.charCodeAt(o + 1) : 0,
            55296 <= e && e <= 56319 && 56320 <= i && i <= 57343 && (e = 65536 + ((1023 & e) << 10) + (1023 & i),
                o++),
            e <= 127 ? n += String.fromCharCode(e) : e <= 2047 ? n += String.fromCharCode(192 | e >>> 6 & 31, 128 | 63 & e) : e <= 65535 ? n += String.fromCharCode(224 | e >>> 12 & 15, 128 | e >>> 6 & 63, 128 | 63 & e) : e <= 2097151 && (n += String.fromCharCode(240 | e >>> 18 & 7, 128 | e >>> 12 & 63, 128 | e >>> 6 & 63, 128 | 63 & e));
        return n
    }

    function f(t) {
        for (var e = Array(t.length >> 2), i = 0; i < e.length; i++)
            e[i] = 0;
        for (i = 0; i < 8 * t.length; i += 8)
            e[i >> 5] |= (255 & t.charCodeAt(i / 8)) << i % 32;
        return e
    }

    function p(t) {
        for (var e = "", i = 0; i < 32 * t.length; i += 8)
            e += String.fromCharCode(t[i >> 5] >>> i % 32 & 255);
        return e
    }

    function g(t, e) {
        t[e >> 5] |= 128 << e % 32,
            t[14 + (e + 64 >>> 9 << 4)] = e;
        for (var i = 1732584193, n = -271733879, o = -1732584194, s = 271733878, a = 0; a < t.length; a += 16) {
            var r = i,
                c = n,
                h = o,
                l = s;
            n = E(n = E(n = E(n = E(n = N(n = N(n = N(n = N(n = C(n = C(n = C(n = C(n = S(n = S(n = S(n = S(n, o = S(o, s = S(s, i = S(i, n, o, s, t[a + 0], 7, -680876936), n, o, t[a + 1], 12, -389564586), i, n, t[a + 2], 17, 606105819), s, i, t[a + 3], 22, -1044525330), o = S(o, s = S(s, i = S(i, n, o, s, t[a + 4], 7, -176418897), n, o, t[a + 5], 12, 1200080426), i, n, t[a + 6], 17, -1473231341), s, i, t[a + 7], 22, -45705983), o = S(o, s = S(s, i = S(i, n, o, s, t[a + 8], 7, 1770035416), n, o, t[a + 9], 12, -1958414417), i, n, t[a + 10], 17, -42063), s, i, t[a + 11], 22, -1990404162), o = S(o, s = S(s, i = S(i, n, o, s, t[a + 12], 7, 1804603682), n, o, t[a + 13], 12, -40341101), i, n, t[a + 14], 17, -1502002290), s, i, t[a + 15], 22, 1236535329), o = C(o, s = C(s, i = C(i, n, o, s, t[a + 1], 5, -165796510), n, o, t[a + 6], 9, -1069501632), i, n, t[a + 11], 14, 643717713), s, i, t[a + 0], 20, -373897302), o = C(o, s = C(s, i = C(i, n, o, s, t[a + 5], 5, -701558691), n, o, t[a + 10], 9, 38016083), i, n, t[a + 15], 14, -660478335), s, i, t[a + 4], 20, -405537848), o = C(o, s = C(s, i = C(i, n, o, s, t[a + 9], 5, 568446438), n, o, t[a + 14], 9, -1019803690), i, n, t[a + 3], 14, -187363961), s, i, t[a + 8], 20, 1163531501), o = C(o, s = C(s, i = C(i, n, o, s, t[a + 13], 5, -1444681467), n, o, t[a + 2], 9, -51403784), i, n, t[a + 7], 14, 1735328473), s, i, t[a + 12], 20, -1926607734), o = N(o, s = N(s, i = N(i, n, o, s, t[a + 5], 4, -378558), n, o, t[a + 8], 11, -2022574463), i, n, t[a + 11], 16, 1839030562), s, i, t[a + 14], 23, -35309556), o = N(o, s = N(s, i = N(i, n, o, s, t[a + 1], 4, -1530992060), n, o, t[a + 4], 11, 1272893353), i, n, t[a + 7], 16, -155497632), s, i, t[a + 10], 23, -1094730640), o = N(o, s = N(s, i = N(i, n, o, s, t[a + 13], 4, 681279174), n, o, t[a + 0], 11, -358537222), i, n, t[a + 3], 16, -722521979), s, i, t[a + 6], 23, 76029189), o = N(o, s = N(s, i = N(i, n, o, s, t[a + 9], 4, -640364487), n, o, t[a + 12], 11, -421815835), i, n, t[a + 15], 16, 530742520), s, i, t[a + 2], 23, -995338651), o = E(o, s = E(s, i = E(i, n, o, s, t[a + 0], 6, -198630844), n, o, t[a + 7], 10, 1126891415), i, n, t[a + 14], 15, -1416354905), s, i, t[a + 5], 21, -57434055), o = E(o, s = E(s, i = E(i, n, o, s, t[a + 12], 6, 1700485571), n, o, t[a + 3], 10, -1894986606), i, n, t[a + 10], 15, -1051523), s, i, t[a + 1], 21, -2054922799), o = E(o, s = E(s, i = E(i, n, o, s, t[a + 8], 6, 1873313359), n, o, t[a + 15], 10, -30611744), i, n, t[a + 6], 15, -1560198380), s, i, t[a + 13], 21, 1309151649), o = E(o, s = E(s, i = E(i, n, o, s, t[a + 4], 6, -145523070), n, o, t[a + 11], 10, -1120210379), i, n, t[a + 2], 15, 718787259), s, i, t[a + 9], 21, -343485551),
                i = v(i, r),
                n = v(n, c),
                o = v(o, h),
                s = v(s, l)
        }
        return [i, n, o, s]
    }

    function _(t, e, i, n, o, s) {
        return v((a = v(v(e, t), v(n, s))) << (r = o) | a >>> 32 - r, i);
        var a, r
    }

    function S(t, e, i, n, o, s, a) {
        return _(e & i | ~e & n, t, e, o, s, a)
    }

    function C(t, e, i, n, o, s, a) {
        return _(e & n | i & ~n, t, e, o, s, a)
    }

    function N(t, e, i, n, o, s, a) {
        return _(e ^ i ^ n, t, e, o, s, a)
    }

    function E(t, e, i, n, o, s, a) {
        return _(i ^ (e | ~n), t, e, o, s, a)
    }

    function v(t, e) {
        var i = (65535 & t) + (65535 & e);
        return (t >> 16) + (e >> 16) + (i >> 16) << 16 | 65535 & i
    }
}
string = 'hello';
console.log(md5(string));
Phap
  • 17
  • 2
0

Considering the thoughts from http://www.thoughtcrime.org/blog/the-cryptographic-doom-principle/ (in short: FIRST encrypt, THEN authenticate. Afterwards FIRST verify, THEN decrypt) I have implemented the following solution in node.js:

function encrypt(text,password){
  var cipher = crypto.createCipher(algorithm,password)
  var crypted = cipher.update(text,'utf8','hex')
  crypted += cipher.final('hex');
  return crypted;
}

function decrypt(text,password){
  var decipher = crypto.createDecipher(algorithm,password)
  var dec = decipher.update(text,'hex','utf8')
  dec += decipher.final('utf8');
  return dec;
}

function hashText(text){
    var hash = crypto.createHash('md5').update(text).digest("hex");
    //console.log(hash); 
    return hash;
}

function encryptThenAuthenticate(plainText,pw)
{
    var encryptedText = encrypt(plainText,pw);
    var hash = hashText(encryptedText);
    return encryptedText+"$"+hash;
}
function VerifyThenDecrypt(encryptedAndAuthenticatedText,pw)
{
    var encryptedAndHashArray = encryptedAndAuthenticatedText.split("$");
    var encrypted = encryptedAndHashArray[0];
    var hash = encryptedAndHashArray[1];
    var hash2Compare = hashText(encrypted);
    if (hash === hash2Compare)
    {
        return decrypt(encrypted,pw); 
    }
}

It can be tested with:

var doom = encryptThenAuthenticate("The encrypted text",user.cryptoPassword);
console.log(VerifyThenDecrypt(doom,user.cryptoPassword));

Hope this helps :-)

batomaeus
  • 156
  • 1
  • 1
  • 8
0

Even if the hash is not for security, you can use sha instead of md5. In my opinion, the people should forget about md5 for now, it's in the past!

The normal nodejs sha256 is deprecated. So, you have two alternatives for now:

var shajs = require('sha.js')  - https://www.npmjs.com/package/sha.js (used by Browserify)

var hash = require('hash.js')  - https://github.com/indutny/hash.js

I prefer using shajs instead of hash, because I consider sha the best hash function nowadays and you don't need a different hash function for now. So to get some hash in hex you should do something like the following:

sha256.update('hello').digest('hex')
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Maf
  • 696
  • 1
  • 8
  • 23
0

you can use crypto-js javaScript library of crypto standards, there is easiest way to generate sha256 or sha512

const SHA256 = require("crypto-js/sha256");
const SHA512 = require("crypto-js/sha512");

let password = "hello"
let hash_256 = SHA256 (password).toString();
let hash_512 = SHA512 (password).toString();

Mohammad Yaser Ahmadi
  • 4,664
  • 3
  • 17
  • 39
-5

Password hashing in NodeJs using PBKDF2

const pbkdf2 = require("pbkdf2");
const crypto = require("crypto");

// UserSchema
//...

// Method to create pbkdf2 hash from plain text
UserSchema.methods.createHash = async function (plainTextPassword) {

  // Generate a salt and then create hash
  const salt = crypto.randomBytes(16).toString("hex");
  const hashedPassword = pbkdf2
    .pbkdf2Sync(plainTextPassword, salt, 10, 32, "sha512")
    .toString("hex");

  // Saving both the dynamic salt and hash in the Database
  return [salt, hashedPassword].join("#");
};

// Validating the password with pbkdf2 hash
UserSchema.methods.validatePassword = async function (candidatePassword) {
  const hashedPassword = this.password_hash.split("#")[1];
  const salt = this.password_hash.split("#")[0];

  const hash = pbkdf2
    .pbkdf2Sync(candidatePassword, salt, 10, 32, "sha512")
    .toString("hex");

  if (hash === hashedPassword) {
    return true;
  }
  return false;
};

module.exports.User = mongoose.model("User", UserSchema);

Password hashing in NodeJs using Argon2

const argon2 = require("argon2");

// UserSchema
...

// Method to generate Hash from plain text  using argon2
UserSchema.methods.createHash = async function (plainTextPassword) {
    // return password hash
    return await argon2.hash(plainTextPassword);
};

// Method to validate the entered password using argon2
UserSchema.methods.validatePassword = async function (candidatePassword) {
  return await argon2.verify(this.password_hash, candidatePassword)
};

module.exports.User = mongoose.model("User", UserSchema);

This article can help in setup to execute with a demo project. https://mojoauth.com/blog/hashing-passwords-in-nodejs/