March 11, 2025β€’Updated on May 19, 2025

AES

cryptography

AES

πŸ” How to Encrypt and Decrypt Data Using AES-256-CBC in Node.js

Content image

Encryption is a fundamental technique used to protect sensitive data from unauthorized access. Whether it's securing user passwords, confidential files, or communications, encryption ensures that your data remains private and safe from prying eyes.

In this blog post, we'll explore how to use Node.js's built-in crypto module to perform AES-256-CBC encryption and decryption. You'll learn the basics of cryptography, how AES encryption works, and see a practical example with code!


πŸ” What is Cryptography?

Cryptography is the science of securing communication so that only authorized parties can access the information. It helps protect data from hackers, ensures privacy, and is widely used in banking systems, messaging apps, online payments, digital signatures, and more.


Types of Cryptography

  • Symmetric Encryption – Uses the same key for both encryption and decryption.
  • Asymmetric Encryption – Uses a public key for encryption and a private key for decryption.
  • Hashing – One-way function that converts data into a fixed-size hash; no decryption possible.

  • What is AES Encryption?

    AES (Advanced Encryption Standard) is a widely used symmetric encryption method that converts readable data into scrambled ciphertext using a secret key. The same key is then used to decrypt the data back to its original form.

    Key Features of AES

  • Fast and Secure: Adopted worldwide including by governments and banks.
  • Key Sizes: Supports 128-bit, 192-bit, and 256-bit keys.
  • Common Use Cases: Secure messaging, password storage, file encryption, and more.

  • Generating a Secure Secret Key

    A strong secret key is the foundation of secure AES encryption. Below is a function that generates a random 256-bit key (32 bytes) encoded as a hexadecimal string for ease of use.

    javascript
    javascript
    CopyEdit
    const crypto = require("crypto");
    const generateSecretKey = () => {
    const keyLength = 32; // 32 bytes = 256 bits
    return crypto.randomBytes(keyLength).toString("hex");
    };
    const secretKey = generateSecretKey();
    console.log("Generated Secret Key:", secretKey);

    Each time you run this, you'll get a unique 64-character hex string like:

    plain text
    vbnet
    CopyEdit
    Generated Secret Key: e9f3a8b62d4c89f7b10c3e9d58723a1f7d2b6a9c5e1f4d8c7b2e0f6a9c3d2b1e

    Understanding AES-256-CBC Encryption

    AES-256-CBC stands for:

  • AES: Advanced Encryption Standard
  • 256: Uses a 256-bit key
  • CBC: Cipher Block Chaining mode
  • In CBC mode, each block of plaintext is XORed with the previous ciphertext block before being encrypted. This chaining adds security but requires an Initialization Vector (IV) to start the process, ensuring that encrypting the same data twice produces different ciphertext.


    The Encryption Process in Node.js

    Here’s a step-by-step encryption function:

    javascript
    javascript
    CopyEdit
    const crypto = require("crypto");
    // Sample data to encrypt
    const data = [
    { _id: "john", username: "DevX@123", password: "1200012" },
    { _id: "john2", username: "DevX@1232", password: "12000122" },
    ];
    // Encrypt data with AES-256-CBC
    const encryptData = (data, secretKey) => {
    const algorithm = "aes-256-cbc";
    const iv = crypto.randomBytes(16); // 16-byte random IV
    const cipher = crypto.createCipheriv(algorithm, Buffer.from(secretKey, "hex"), iv);
    let encrypted = cipher.update(JSON.stringify(data), "utf-8", "hex");
    encrypted += cipher.final("hex");
    // Return IV and encrypted data as hex strings separated by colon
    return iv.toString("hex") + ":" + encrypted;
    };
    const secretKey = generateSecretKey();
    const encryptedData = encryptData(data, secretKey);
    console.log("Secret Key:", secretKey);
    console.log("Encrypted Data:", encryptedData);

    Explanation:

  • A random IV is generated for each encryption to ensure unique ciphertext.
  • The JSON data is converted to a UTF-8 string, then encrypted to a hex string.
  • The IV is prepended (separated by :) because it is needed for decryption.

  • Decryption Process

    To restore the original data, you need to extract the IV and use the same secret key:

    javascript
    javascript
    CopyEdit
    const decryptData = (encryptedData, secretKey) => {
    const algorithm = "aes-256-cbc";
    const [ivHex, encryptedText] = encryptedData.split(":");
    const decipher = crypto.createDecipheriv(
    algorithm,
    Buffer.from(secretKey, "hex"),
    Buffer.from(ivHex, "hex")
    );
    let decrypted = decipher.update(encryptedText, "hex", "utf-8");
    decrypted += decipher.final("utf-8");
    return JSON.parse(decrypted);
    };
    const decryptedData = decryptData(encryptedData, secretKey);
    console.log("Decrypted Data:", decryptedData);

    How the Encoding Works

  • UTF-8: Converts the JSON string into bytes for encryption.
  • Hexadecimal (hex): Converts bytes into human-readable characters for storage and transmission.
  • The IV and ciphertext are stored in hex form for easy sharing and safe transport.

  • Why Use AES-256-CBC?

  • Strong security: AES-256 is widely trusted and government-approved.
  • Randomness: The IV ensures different ciphertext for identical data.
  • Performance: Fast enough for most real-world applications.
  • Simplicity: Symmetric encryption means only one secret key is required.

  • Summary: Full Code Example

    javascript
    javascript
    CopyEdit
    const crypto = require("crypto");
    const generateSecretKey = () => crypto.randomBytes(32).toString("hex");
    const encryptData = (data, secretKey) => {
    const algorithm = "aes-256-cbc";
    const iv = crypto.randomBytes(16);
    const cipher = crypto.createCipheriv(algorithm, Buffer.from(secretKey, "hex"), iv);
    let encrypted = cipher.update(JSON.stringify(data), "utf-8", "hex");
    encrypted += cipher.final("hex");
    return iv.toString("hex") + ":" + encrypted;
    };
    const decryptData = (encryptedData, secretKey) => {
    const algorithm = "aes-256-cbc";
    const [ivHex, encryptedText] = encryptedData.split(":");
    const decipher = crypto.createDecipheriv(
    algorithm,
    Buffer.from(secretKey, "hex"),
    Buffer.from(ivHex, "hex")
    );
    let decrypted = decipher.update(encryptedText, "hex", "utf-8");
    decrypted += decipher.final("utf-8");
    return JSON.parse(decrypted);
    };
    // Usage
    const secretKey = generateSecretKey();
    console.log("Secret Key:", secretKey);
    const data = [
    { _id: "john", username: "DevX@123", password: "1200012" },
    { _id: "john2", username: "DevX@1232", password: "12000122" },
    ];
    const encryptedData = encryptData(data, secretKey);
    console.log("Encrypted Data:", encryptedData);
    const decryptedData = decryptData(encryptedData, secretKey);
    console.log("Decrypted Data:", decryptedData);

    Final Thoughts

    AES-256-CBC encryption combined with Node.js's crypto module offers a powerful, secure way to protect your data. Remember:

  • Always use secure random keys.
  • Store your keys safely; if lost, data can’t be decrypted.
  • Use a random IV for every encryption.
  • Encrypt sensitive data before saving or transmitting.

  • If you found this post helpful or have questions, feel free to leave a comment below. Happy encrypting! πŸ”’

    Latest Articles

    More articles ➜
    Cover image for Multer  Guide For Begginers
    backend

    Multer Guide For Begginers

    How to use multer

    backend
    Cover image for TanStack Query: A Powerful Tool for Data Management
    frontend

    TanStack Query: A Powerful Tool for Data Management

    A simple and educational project showing how to use TanStack Query (React Query) to fetch, create, and manage blog posts using React + TypeScript.

    frontend