Logo

dev-resources.site

for different kinds of informations.

Secure Text Encryption and Decryption with Vanilla JavaScript

Published at
12/3/2024
Categories
encryption
decryption
vanilla
javascript
Author
eddiegulay
Author
10 person written this
eddiegulay
open
Secure Text Encryption and Decryption with Vanilla JavaScript

In today’s digital age, securing sensitive information like API keys, passwords, and user data is more critical than ever. A robust encryption and decryption strategy can prevent unauthorized access and ensure data confidentiality. In this blog post, we’ll explore how to encrypt and decrypt text using vanilla JavaScript, leveraging the Web Crypto API for a modern, secure approach.

Why Use Encryption?

Encryption transforms readable data (plaintext) into a scrambled format (ciphertext) that can only be read if decrypted with the correct key. This ensures that even if someone intercepts the encrypted data, it remains meaningless without the key. A solid encryption mechanism protects:

  • API keys stored in your frontend code.
  • Sensitive user information.
  • Any data transferred over insecure channels.

Let’s dive into how you can implement this securely in JavaScript.


Encryption and Decryption Using AES-GCM

We’ll use AES-GCM (Advanced Encryption Standard - Galois/Counter Mode), a modern standard that provides both encryption and integrity verification. The steps involve:

  1. Password Derivation: Use PBKDF2 (Password-Based Key Derivation Function 2) to derive a secure key from a password.
  2. Salt and IV: Generate a random salt (to make the password derivation unique) and iv (Initialization Vector) for each encryption.
  3. Encryption: Encrypt the plaintext using AES-GCM.
  4. Decryption: Decrypt the ciphertext using the same password and salt/iv.

Code Implementation

Here is the complete JavaScript implementation.

Utilities for Conversion

We’ll convert between ArrayBuffer and hexadecimal for easy data storage and retrieval:

function arrayBufferToHex(buffer) {
    return [...new Uint8Array(buffer)]
        .map(byte => byte.toString(16).padStart(2, '0'))
        .join('');
}

function hexToArrayBuffer(hex) {
    const bytes = new Uint8Array(hex.length / 2);
    for (let i = 0; i < hex.length; i += 2) {
        bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
    }
    return bytes.buffer;
}
Enter fullscreen mode Exit fullscreen mode

Key Derivation from Password

Use PBKDF2 to derive a strong encryption key:

async function getCryptoKey(password) {
    const encoder = new TextEncoder();
    const keyMaterial = encoder.encode(password);
    return crypto.subtle.importKey(
        'raw',
        keyMaterial,
        { name: 'PBKDF2' },
        false,
        ['deriveKey']
    );
}

async function deriveKey(password, salt) {
    const keyMaterial = await getCryptoKey(password);
    return crypto.subtle.deriveKey(
        {
            name: 'PBKDF2',
            salt: salt,
            iterations: 100000,
            hash: 'SHA-256'
        },
        keyMaterial,
        { name: 'AES-GCM', length: 256 },
        false,
        ['encrypt', 'decrypt']
    );
}
Enter fullscreen mode Exit fullscreen mode

Encryption Function

Encrypt text with a password:

async function encryptText(text, password) {
    const encoder = new TextEncoder();
    const salt = crypto.getRandomValues(new Uint8Array(16));
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const key = await deriveKey(password, salt);

    const encrypted = await crypto.subtle.encrypt(
        { name: 'AES-GCM', iv: iv },
        key,
        encoder.encode(text)
    );

    return {
        cipherText: arrayBufferToHex(encrypted),
        iv: arrayBufferToHex(iv),
        salt: arrayBufferToHex(salt)
    };
}
Enter fullscreen mode Exit fullscreen mode

Decryption Function

Decrypt text with the same password:

async function decryptText(encryptedData, password) {
    const { cipherText, iv, salt } = encryptedData;
    const key = await deriveKey(password, hexToArrayBuffer(salt));

    const decrypted = await crypto.subtle.decrypt(
        { name: 'AES-GCM', iv: hexToArrayBuffer(iv) },
        key,
        hexToArrayBuffer(cipherText)
    );

    const decoder = new TextDecoder();
    return decoder.decode(decrypted);
}
Enter fullscreen mode Exit fullscreen mode

Example Usage

Let’s see how to use these functions:

(async () => {
    const text = 'MySecretAPIKey123456';
    const password = 'StrongPassword123!';

    // Encrypt
    const encryptedData = await encryptText(text, password);
    console.log('Encrypted Data:', encryptedData);

    // Decrypt
    const decryptedText = await decryptText(encryptedData, password);
    console.log('Decrypted Text:', decryptedText);
})();
Enter fullscreen mode Exit fullscreen mode

Security Best Practices

  1. Use a Strong Password: The encryption is only as secure as the password you use.
  2. Store Salt and IV Safely: Always save the salt and iv alongside your encrypted data.
  3. Avoid Hardcoding Secrets: Never hardcode sensitive data or passwords in your codebase.
  4. Use HTTPS: Ensure your application uses HTTPS to protect data in transit.

Encrypting sensitive information like API keys is a fundamental step in securing your applications. I use this for API keys mostly.

encryption Article's
30 articles in total
Favicon
Encryption in React Native apps enhances data security, protecting user information and ensuring privacy. However, it also presents challenges, such as performance overhead and complex implementation
Favicon
A Deep Dive into WhatsApp’s Encryption: Identity, Keys, and Message Security
Favicon
The Birthday Paradox: A Statistical Breakdown and How it Relates to Online Security
Favicon
Obfuscating “Hello world!” obfuscate on Python
Favicon
Introducing Inline Cryptography Toolkit: Simplify Encryption, Decryption, and Hashing in VS Code 🚀
Favicon
Advantages of Asymmetric Encryption with Random Public and Symmetric Private Keys
Favicon
Cloud Security Challenges and Encryption, Identity Management, and Compliance
Favicon
Microsoft Certified Azure Administrator Associate Exam (AZ-104) Lab Preparation #5: Azure Disk Encryption
Favicon
Encryption: ciphers, digests, salt, IV
Favicon
The Evolution of Hashing Algorithms: From MD5 to Modern Day
Favicon
Email Security and Data Protection for Startups: Affordable Solutions
Favicon
Understanding SNI (Server Name Indication) and Modern Encryption Solutions
Favicon
What is RSA Asymmetric Encryption? Basics, Principles and Applications
Favicon
Encryption Vs. Decryption: What’s the Difference?
Favicon
Laravel Data Encryption and Decryption
Favicon
Unveiling A Groundbreaking Open-Source Encrypted Machine Learning Framework
Favicon
Secure Text Encryption and Decryption with Vanilla JavaScript
Favicon
Understanding SSL/TLS: The Role of Encryption and Security Protocols in Internet Communication
Favicon
Implications for Encryption and Cybersecurity with Quantum Computing
Favicon
How to Generate Your Own Public and Secret Keys for PGP Encryption
Favicon
Does S/MIME Encrypt Emails and Attachments?
Favicon
What is Token Signing in Software Publisher Certificate?
Favicon
Encryption Symmetric
Favicon
Secret management for the layman
Favicon
JavaScript Base-32 Encryption
Favicon
Comprehensive Encryption and Security Service in NestJS: Argon2 Hashing, Token Generation, and AES Encryption
Favicon
Difference Between Encryption and Hashing 🔐🔑
Favicon
Ransomware Explained: How It Works and Best Defense Mechanisms to Protect Your Data
Favicon
Debunking Most Common Cloud Computing Myths & Misconceptions
Favicon
Implementing HTTP Request and Response Encryption in ASP.NET Core with Custom Attributes

Featured ones: