How to encrypt and decrypt a message in Node.js?

November 30, 2020 - 7 min read

To encrypt and decrypt a message, we can use the createCipheriv() and the createDecipheriv() methods respectively in the crypto module in Node.js.

To encrypt or decrypt a message we need four things:

  • message to be encrypted or decrypted
  • algorithm to use for the encryption and decryption. We will be using the aes-256-cbc (aes 256 cipher block chaining) algorithm to encrypt and decrypt the data.
  • key to encrypt or decrypt the message. This should be an organization or company secret 🤫.
  • iv or initialization vector, it is a random number generated to increase the security of the encryption and decryption.

Jump to the full code →

Encrypt a message

First, let's require the crypto module.

// get crypto module
const crypto = require("crypto");

Now we need to make the iv (initialization vector: Bytes which are generated randomly). For that, the crypto module provides a simple function called randomBytes() which we can use to generate random bytes of a specified length. Let's pass the number of bytes 16 as an argument to the function like this,

// get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);
  • The function returns a Buffer of random data.

NOTE: There is an issue with randomBytes() function in the crypto module See this to know more. That why we are using the slice() method to slice the data to remove some extra data being added by the randomBytes() function.

We need to define the message and the secret key to be encrypted.

  • The key should have a length of 32 characters or 32 bytes (since the algorithm uses 256 bits).
// get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

Now let's make the encrypter function using the createCipheriv() function from the crypto module and pass the algorithm we need to use in our case aes-256-cbc as the first argument, the key as the second argument, and the iv as the third argument.

// get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = crypto.createCipheriv("aes-256-cbc", key, iv);

We have made the encrypter function. Now let's encrypt our message using the update() method on the encrypter and pass the message as the first argument, the input encoding (in our case utf8) as the second argument, and the output encoding (in our case hex) as the third argument like this,

// get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = createCipheriv("aes-256-cbc", key, iv);

// encrypt the message
// set the input encoding
// and the output encoding
let encryptedMsg = encrypter.update(message, "utf8", "hex");

Now we need to tell the encrypter to stop the encryption once and for all using the final() method on the encrypter and append data returned by the final() method to it. Once the final() method is called encrypter cannot be used again to encrypt any more data.

The final() method returns a buffer so we need to set an output encoding of hex and append the hex value to the end of the encrypted message like this,

//  get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = crypto.createCipheriv("aes-256-cbc", key, iv);

// encrypt the message
// set the input encoding
// and the output encoding
let encryptedMsg = encrypter.update(message, "utf8", "hex");

// stop the encryption using
// the final method and set
// output encoding to hex
encryptedMsg += encrypter.final("hex");

console.log(encryptedMsg);

Yay! We have encrypted our message 🦄. The encryptedMsg will be different each time.

Decrypting a message

Decrypting a message follows the same format and steps followed while encrypting a message.

To decrypt a message we can use the createDecipheriv() function from the crypto module and pass the algorithm aes-256-cbc as the first argument, the key used while encrypting the message as the second argument, and the iv used while encrypting the message as the third argument.

It can be done like this,

//  get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = crypto.createCipheriv("aes-256-cbc", key, iv);

// encrypt the message
// set the input encoding
// and the output encoding
let encryptedMsg = encrypter.update(message, "utf8", "hex");

// stop the encryption using
// the final method and set
// output encoding to hex
encryptedMsg += encrypter.final("hex");

console.log(encryptedMsg);

// make the decrypter function
const decrypter = crypto.createDecipheriv("aes-256-cbc", key, iv);

After that, we can use the update() method on the decrypter to decrypt the encrypted message by passing the encryptedMsg as the first argument.

The second argument is the input encoding of the encrypted message in our case it is hex and the third argument is the output encoding after decryption, in our case, it should be utf8.

It can be done like this,

//  get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = crypto.createCipheriv("aes-256-cbc", key, iv);

// encrypt the message
// set the input encoding
// and the output encoding
let encryptedMsg = encrypter.update(message, "utf8", "hex");

// stop the encryption using
// the final method and set
// output encoding to hex
encryptedMsg += encrypter.final("hex");

console.log(encryptedMsg);

// make the decrypter function
const decrypter = crypto.createDecipheriv("aes-256-cbc", key, iv);

// decrypt the message
// set the input encoding
// and the output encoding
let decryptedMsg = decrypter.update(encryptedMsg, "hex", "utf8");

Now finaly let's use the final() method on the decrypter to stop the decryption and set the output encoding to utf8 like this,

//  get crypto module
const crypto = require("crypto");

// generate 16 bytes of random data
const iv = crypto.randomBytes(16).toString("hex").slice(0, 16);

// our secret message
const message = "Hello There, I should be a secret";

// secret key
const key = "12345678123456781234567812345678";

// make the encrypter function
const encrypter = crypto.createCipheriv("aes-256-cbc", key, iv);

// encrypt the message
// set the input encoding
// and the output encoding
let encryptedMsg = encrypter.update(message, "utf-8", "hex");

// stop the encryption using
// the final method and set
// output encoding to hex
encryptedMsg += encrypter.final("hex");

console.log("Encrypted message: " + encryptedMsg);

// make the decrypter function
const decrypter = crypto.createDecipheriv("aes-256-cbc", key, iv);

// decrypt the message
// set the input encoding
// and the output encoding
let decryptedMsg = decrypter.update(encryptedMsg, "hex", "utf8");

// stop the decryption using
// the final method and set
// output encoding to utf8
decryptedMsg += decrypter.final("utf8");

console.log("Decrypted message: " + decryptedMsg);

And we have successfully decrypted the encrypted message. 🥳

See code live in repl.it.

Feel free to share if you found this useful 😃.