AES-GCM with PBKDF2

Encrypt or decrypt text locally using AES-GCM or AES-CBC with PBKDF2 and SHA-256 derived keys.

Tokens follow the format mode.salt.iv.ciphertext using Base64 components.

How AES-GCM and PBKDF2 work together

AES-GCM is an authenticated encryption mode: it encrypts data while calculating an integrity tag that proves the ciphertext has not been tampered with. HashyTools derives the AES key from your password using PBKDF2 with SHA-256 so human phrases gain the entropy they need to resist brute-force attacks.

Key derivation steps

  1. Generate a 16 byte salt with crypto.getRandomValues.
  2. Feed the password and salt into PBKDF2 with SHA-256.
  3. Run 100,000 iterations to slow down offline cracking attempts.
  4. Import the derived bytes as a 256-bit AES key.

Why it matters

  • Authenticated encryption: GCM validates ciphertext before revealing plaintext.
  • Nonce safety: Each encryption uses a fresh 12 byte IV so tags remain unique.
  • Shareable tokens: Salts and IVs live inside the token, so collaborators only need the password.
  • Offline privacy: All steps run in your browser with the Web Crypto API.

AES-GCM vs AES-CBC

Both modes secure data when implemented correctly, but they carry different requirements. Use the matrix below to pick the mode that aligns with your interoperability and security constraints.

Characteristic AES-GCM AES-CBC
Integrity protection Built-in authentication tag. Detects tampering automatically. Requires separate HMAC to verify authenticity.
Performance Fast and parallelizable on modern CPUs with AES-NI. Sequential; cannot be parallelized across blocks.
Nonce/IV requirements Must never reuse the same IV with the same key. IV must be unpredictable, but reuse has less catastrophic impact.
Interoperability Supported in modern browsers, APIs, TLS 1.3, and WebCrypto. Common in legacy stacks, older TLS versions, and hardware HSMs.

Use cases for browser-based AES

Encrypting data locally prevents sensitive information from touching third-party servers. These scenarios highlight when the tool is especially helpful.

Quick secret sharing

Encrypt API keys or environment variables before dropping them into chat or ticketing tools. Recipients decrypt locally with the agreed password.

Client-side storage

Protect notes or configuration files before persisting them in localStorage or IndexedDB so accidental leaks reveal only ciphertext.

Testing interoperability

Generate reference ciphertext for automation tests. The Base64 token encodes every parameter your backend needs to replicate the key schedule.

Implementation checklist

Follow these guidelines when integrating AES tokens into larger systems.

Quick question

Do you need interoperability with a specific backend language or framework for your tokens?

JavaScript (Web Crypto)

async function deriveKey(password, salt) {
  const enc = new TextEncoder();
  const keyMaterial = await crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']);
  return crypto.subtle.deriveKey(
    { name: 'PBKDF2', salt, iterations: 100_000, hash: 'SHA-256' },
    keyMaterial,
    { name: 'AES-GCM', length: 256 },
    false,
    ['encrypt', 'decrypt']
  );
}

async function encryptText(password, plaintext) {
  const enc = new TextEncoder();
  const salt = crypto.getRandomValues(new Uint8Array(16));
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const key = await deriveKey(password, salt);
  const cipher = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, enc.encode(plaintext));
  return [
    'gcm',
    btoa(String.fromCharCode(...salt)),
    btoa(String.fromCharCode(...iv)),
    btoa(String.fromCharCode(...new Uint8Array(cipher)))
  ].join('.');
}

Python (cryptography)

from base64 import b64encode, b64decode
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

def encrypt_text(password: str, plaintext: str) -> str:
    salt = os.urandom(16)
    iv = os.urandom(12)
    kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100_000)
    key = kdf.derive(password.encode('utf-8'))
    aesgcm = AESGCM(key)
    cipher = aesgcm.encrypt(iv, plaintext.encode('utf-8'), associated_data=None)
    return 'gcm.' + '.'.join(
        b64encode(part).decode('ascii') for part in (salt, iv, cipher)
    )

AES encryption FAQ

What is AES-GCM and why is it preferred?

AES-GCM provides authenticated encryption, combining confidentiality with integrity tags so tampering is detected before decryption. It is efficient and well supported in modern runtimes.

Why does the tool derive keys with PBKDF2 and SHA-256?

PBKDF2 stretches low-entropy passwords into strong 256-bit AES keys using a unique salt and thousands of SHA-256 iterations, raising the cost of offline attacks.

When should I use AES-CBC instead of AES-GCM?

Choose AES-CBC only when interoperating with older systems that cannot handle GCM. Always pair CBC with an HMAC so you can detect modification attacks.

What information is stored in the generated token?

The token embeds the mode, salt, IV, and ciphertext as Base64 segments. Anyone with the password can recompute the derived key, apply the IV, and recover the plaintext.

Does this AES tool send any data to a server?

No. All encryption and decryption happens locally via the Web Crypto API—your plaintext and passwords never leave the browser.