# How to encrypt and decrypt data in Node.js

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Jul 30, 2020, updated Oct 1, 2022. Topics: Node.js.
Canonical URL: https://attacomsian.com/blog/nodejs-encrypt-decrypt-data

> Learn how to encrypt and decrypt strings, numbers, buffers, and streams by using the Node.js built-in crypto module.

Node.js provides a built-in module called `crypto` that you can use to encrypt and decrypt strings, numbers, buffers, streams, and more. This module offers cryptographic functionality that includes a set of wrappers for OpenSSL's hash, HMAC, cipher, decipher, sign, and verify functions.

In this article, you'll learn how to use Node.js `crypto` module to perform cryptographic operations on data. I'll show you how to encrypt data with a secret key and then decrypt it using the same secret key when required.

For the sake of simplicity, I shall use AES (Advanced Encryption System) algorithm CTR encryption mode. Here is a good discussion on [StackOverflow](https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb) for choosing the correct AES encryption mode.

## Create a new project

Create a new directory in your local file system and switch to it by typing the following:

```bash
$ mkdir crypto && cd crypto
```

Now execute the following command to initialize a new Node.js project:

```bash
$ npm init -y
```

The above command will create a new `package.json` file in the root directory. Make sure that you have already [installed Node.js](https://attacomsian.com/blog/install-nodejs-npm-ubuntu) on your machine before issuing the above command.

By default, the `crypto` module is already included in pre-built Node.js binaries. But if you have manually installed Node.js, `crypto` may not be shipped with it. However, you can install it by executing the following command:

```bash
$ npm install crypto --save
```

## Encrypt and decrypt text

Let us create the `crypto.js` file in the project's root directory and define our encryption and decryption functions as shown below:

<p class="file-desc"><span>crpyto.js</span></p>

```javascript
const crypto = require('crypto')

const algorithm = 'aes-256-ctr'
const secretKey = 'vOVH6sdmpNWjRRIqCc7rdxs01lwHzfr3'

const encrypt = text => {
  const iv = crypto.randomBytes(16)

  const cipher = crypto.createCipheriv(algorithm, secretKey, iv)

  const encrypted = Buffer.concat([cipher.update(text), cipher.final()])

  return {
    iv: iv.toString('hex'),
    content: encrypted.toString('hex')
  }
}

const decrypt = hash => {
  const decipher = crypto.createDecipheriv(algorithm, secretKey, Buffer.from(hash.iv, 'hex'))

  const decrpyted = Buffer.concat([decipher.update(Buffer.from(hash.content, 'hex')), decipher.final()])

  return decrpyted.toString()
}

module.exports = {
  encrypt,
  decrypt
}
```

The following example demonstrates how you can encrypt and decrypt text data (strings, numbers, etc.) by using the above functions:

<p class="file-desc"><span>crpyto-text.js</span></p>

```javascript
const { encrypt, decrypt } = require('./crypto')

const hash = encrypt('Hello World!')

console.log(hash)

// {
//     iv: '237f306841bd23a418878792252ff6c8',
//     content: 'e2da5c6073dd978991d8c7cd'
// }

const text = decrypt(hash)

console.log(text) // Hello World!
```

## Encrypt and decrypt buffers

You can also encrypt and decrypt buffers by using the functions defined above. Just pass the buffer in place of the string, and it should work:

<p class="file-desc"><span>crpyto-buffer.js</span></p>

```javascript
const { encrypt, decrypt } = require('./crypto')

const hash = encrypt(Buffer.from('Hello World!', 'utf8'))

console.log(hash)

// {
//     iv: '692e44dbbea073fc1a8d1c37ea68dffa',
//     content: 'bbffd902d55d7a00f3a0504e'
// }

const text = decrypt(hash)

console.log(text) // Hello World!
```

## Encrypt and decrypt streams

You can also encrypt and decrypt streams by using the `crypto` module, as shown in the following example:

<p class="file-desc"><span>crpyto-stream.js</span></p>

```javascript
const crypto = require('crypto')
const fs = require('fs')

const algorithm = 'aes-256-ctr'
const secretKey = 'vOVH6sdmpNWjRRIqCc7rdxs01lwHzfr3'
const iv = crypto.randomBytes(16)

// input file
const r = fs.createReadStream('file.txt')

// encrypt content
const encrypt = crypto.createCipheriv(algorithm, secretKey, iv)

// decrypt content
const decrypt = crypto.createDecipheriv(algorithm, secretKey, iv)

// write file
const w = fs.createWriteStream('file.out.txt')

// start pipe
r.pipe(encrypt).pipe(decrypt).pipe(w)
```

> **Source Code:** Download the complete source code of this project from [GitHub](https://github.com/attacomsian/code-examples/tree/master/nodejs/crypto), available under the MIT license.

## Conclusion

In this article, we looked at how to perform cryptographic operations on text, buffers, and streams using the Node.js built-in [crypto](https://nodejs.org/docs/latest/api/crypto.html) module. This is extremely useful if you need to encrypt sensitive data like secret keys before storing them in a database.
