Various Types of Hashes Cryptography in NodeJS

Written by: Bagus Facsi Aginsa
Published at: 02 Mar 2024


In this digital era, security and data privacy is a top concern for developers. We should not let our user’s data be stolen by irresponsible people. 3 common cryptography techniques are used to secure your data as developers. Those techniques are:

  1. Hash
  2. Symmetric Encryption
  3. Asymmetric Encryption

In this article, we will look at specifically hash. Let’s see the implementation in NodeJS.

NodeJS Library for Hash Cryptography And Its Algorithm

To create a hash, we can use a built-in nodejs library that is crypto. you just have to import them like this:

let crypto = require("crypto")

This library supports many kinds of hash algorithms. To get all of the supported algorithms, you can use this method:

let crypto = require("crypto")

console.log(crypto.getHashes())

// ['RSA-MD5','RSA-RIPEMD160','RSA-SHA1','RSA-SHA1-2','RSA-SHA224',
// 'RSA-SHA256','RSA-SHA3-224','RSA-SHA3-256','RSA-SHA3-384',
// 'RSA-SHA3-512','RSA-SHA384','RSA-SHA512','RSA-SHA512/224',
// 'RSA-SHA512/256','RSA-SM3','blake2b512','blake2s256',
// 'id-rsassa-pkcs1-v1_5-with-sha3-224','id-rsassa-pkcs1-v1_5-with-sha3-256',
// 'id-rsassa-pkcs1-v1_5-with-sha3-384','id-rsassa-pkcs1-v1_5-with-sha3-512',
// 'md5','md5-sha1','md5WithRSAEncryption','ripemd','ripemd160',
// 'ripemd160WithRSA','rmd160','sha1','sha1WithRSAEncryption','sha224',
// 'sha224WithRSAEncryption', 'sha256','sha256WithRSAEncryption','sha3-224',
// 'sha3-256','sha3-384','sha3-512','sha384','sha384WithRSAEncryption',
// 'sha512','sha512-224','sha512-224WithRSAEncryption',
// 'sha512-256','sha512-256WithRSAEncryption','sha512WithRSAEncryption',
// 'shake128','shake256','sm3','sm3WithRSAEncryption','ssl3-md5',
// 'ssl3-sha1']

As you can see we can use many algorithms, 2 of them are sha256 and sha512 which is the most popular one.

Basic Hash Cryptography in NodeJS

The first method in crypto library that is used to hash is createHash(). This method provides a basic hashing functionality in nodejs. You will probably not use this method in real-world applications because it is just not as safe as the other method. To use this method, you can look at this code piece:

let crypto = require("crypto")

let hash = (text) => {

    let hash = crypto.createHash("sha256")

    hash.update(text)

    return hash.digest("hex")
}

let compare = (text, hashedText) = {

    let hashed = hash(text)

    return (hashed === hashedText) ? true : false
}

module.exports = {
    hash,
    compare
}

Notes!

Don’t use this method for hashing passwords, it is not safe!

In this example, we use SHA256 algorithm, alternatively, you can use SHA512 to create a stronger hash.

HMAC Cryptography in NodeJS

HMAC is a Hash-based Message Authentication Code. It is a cryptographic authentication technique that uses a hash function and a secret key.

The most popular HMAC techniques are HMAC-SHA256 and HMAC-SHA512.

To create a hmac, you can use createHmac() method. This method is usually combined with encryption cryptography such as AES to create a message authentication code. We will try to create an HMAC-SHA256 as an example of how to use this method:

let crypto = require("crypto")

let hash = (text) => {

    let hmac = crypto.createHmac("sha256", "mysupersecret")

    hmac.update(text)

    return hmac.digest("hex")
}

let compare = (text, hashedText) => {
    let hashed = hash(text)

    return (hashed === hashedText) ? true : false
}

module.exports = {
    hash,
    compare
}

You can see that it uses a secret mysupersecret to hash the text. To create SHA512, you just have to change the hash algorithm from sha256 to sha512 on the code snippet above.

Notes!

Don’t use this method for hashing passwords, it is not safe!

PBKDF2 Cryptography in NodeJS

PBKDF2 is Password-Based Key Derivation Function (version) 2. It is a hash technique that is used specifically for generating passwords because it is deliberately slow to compute by using many iteration processes.

The most popular PBKDF2 techniques are PBKDF2-HMAC-256 and PBKDF2-HMAC-512.

We will try to create a PBKDF2-HMAC-SHA256 as an example of how to use this method:

let crypto = require("crypto)

let hash = (salt, text) => {

    let algorithm = "sha256"
    let iteration = algorithm === "sha512" ? 210000 : 600000

    return new Promise((resolve, reject) => {

        pbkdf2(text, salt, iteration, 64, algorithm, (err, derivedKey) => {
            if (err) return reject(err)

            return resolve(salt + "." + derivedKey.toString("hex"))
        })
    })
}

let compare = async (text, hashedText) => {

    let salt = hashedText.split(".")[0]

    let hashed = await hash(salt, text)

    return (hashed === hashedText) ? true : false
}

module.exports = {
    hash,
    compare
}

Before calling the hash function, you can generate the randomSalt value just like this

let randomSalt = crypto.randomBytes(16).toString("hex")

Also, notice that we return the randomSalt together with the derivedKey in this hash function example. It is common practice that we use a unique salt every time we create a new password and embed it together with the password to make the password unpredictable.

When comparing the text and hashedText, first we must extract the salt and then generate the hash with the extracted salt value.

Scrypt Cryptography in NodeJS

Scrypt is the same as pbkdf2, a password-based key derivation function. Besides being deliberately slow, it is designed to require a large (and adjustable) amount of memory to compute. The purpose of this is to make it harder to crack parallelly using devices like GPGPUs or custom ASIC / FPGA hardware.

To use this method, you can look at this code piece:

let crypto = require("crypto)

let hash = (salt, text) => {

    return new Promise((resolve, reject) => {

        pbkdf2(text, randomSalt, 64, (err, derivedKey) => {
            if (err) return reject(err)

            return resolve(randomSalt + "." + derivedKey.toString("hex"))
        })
    })    
}

let compare = async (text, hashedText) => {
    let salt = hashedText.split(".")[0]

    let hashed = await hash(salt, text)

    return (hashed === hashedText) ? true : false
}

module.exports = {
    hash,
    compare
}

Same as PBKDF2, Before calling the hash function, you can generate the randomSalt value just like this

let randomSalt = crypto.randomBytes(16).toString("hex")

Notice that we also return the randomSalt together with the derivedKey to make the password unpredictable.

That’s it. Those are the 4 types of hash that we can use in NodeJS using the crypto library.