Home > Web Front-end > JS Tutorial > Secure Text Encryption and Decryption with Vanilla JavaScript

Secure Text Encryption and Decryption with Vanilla JavaScript

Linda Hamilton
Release: 2024-12-08 03:37:10
Original
1031 people have browsed it

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;
}
Copy after login
Copy after login

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']
    );
}
Copy after login

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)
    };
}
Copy after login

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);
}
Copy after login

Example Usage

Let’s see how to use these functions:

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;
}
Copy after login
Copy after login

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.

The above is the detailed content of Secure Text Encryption and Decryption with Vanilla JavaScript. For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template