AES Encryption Tool — GCM, CBC & CTR
Free online AES encryption — AES-128/192/256, GCM/CBC/CTR, passphrase (PBKDF2) or raw key. Runs 100% in your browser; nothing is uploaded.
Advanced options
Never reuse an IV with the same key. Leave blank to generate a secure random IV.
What Is AES Encryption?
AES (the Advanced Encryption Standard) is a symmetric block cipher standardized by NIST in FIPS 197 in 2001, based on the Rijndael design by Joan Daemen and Vincent Rijmen. It encrypts data in fixed 128-bit blocks using a 128-, 192-, or 256-bit key, and the same key both encrypts and decrypts. It is the workhorse of modern cryptography, protecting everything from HTTPS traffic to disk encryption.
A raw block cipher only scrambles one 16-byte block, so AES is always run inside a mode of operation that chains blocks together. This tool offers three, all provided natively by the browser's Web Crypto API: GCM, CBC, and CTR. GCM (Galois/Counter Mode, NIST SP 800-38D) is the recommended default because it is authenticated — it produces a 128-bit authentication tag alongside the ciphertext, so any tampering is detected when you decrypt. CBC and CTR provide confidentiality only; on their own they cannot tell you whether the ciphertext was altered, which is why TLS 1.3 (RFC 8446) dropped every CBC cipher suite in favor of authenticated modes like GCM.
You will notice there is no ECB mode here, and that is deliberate. ECB encrypts every identical plaintext block to the same ciphertext block, so large-scale structure leaks straight through — the famous 'ECB penguin' image is still visibly a penguin after encryption. The Web Crypto API omits ECB for exactly this reason (it implements only AES-CBC, AES-CTR, and AES-GCM), and so do we. If you need to interoperate with a legacy system that used ECB, treat that as a reason to migrate it, not to reproduce the weakness.
Because most people type a passphrase rather than a 32-byte random key, the tool derives the AES key from your passphrase with PBKDF2-HMAC-SHA256 at 600,000 iterations and a 16-byte random salt, matching the current OWASP Password Storage guidance (and NIST SP 800-132, which requires a salt of at least 128 bits). That makes brute-forcing a weak passphrase slow, but it is not magic: this is a tool for learning modes, debugging ciphertext, and one-off personal data — not for protecting production secrets, which belong in a dedicated key-management system. For a strong passphrase, generate one with our random password generator; for a real random key, use the secret key generator.
// AES-256-GCM with a passphrase (PBKDF2-HMAC-SHA256, 600,000 iterations).
// Identical code runs in the browser and in Node.js 20+ via Web Crypto.
async function aesGcmEncrypt(plaintext, passphrase) {
const enc = new TextEncoder();
const salt = crypto.getRandomValues(new Uint8Array(16));
const iv = crypto.getRandomValues(new Uint8Array(12));
const baseKey = await crypto.subtle.importKey(
'raw', enc.encode(passphrase), 'PBKDF2', false, ['deriveKey']);
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' },
baseKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt']);
const ct = new Uint8Array(await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv }, key, enc.encode(plaintext)));
const packed = new Uint8Array([...salt, ...iv, ...ct]); // salt(16) | iv(12) | ct+tag
return btoa(String.fromCharCode(...packed)); // self-contained Base64
} Key Features
GCM authenticated encryption by default
GCM produces the ciphertext plus a 128-bit authentication tag, so decryption fails loudly if a single byte was changed. CBC and CTR are one click away for when you need to interoperate with them.
Self-contained ciphertext
Passphrase mode packs the random salt, IV, and tag into one Base64 string, so whoever decrypts needs only the passphrase — there are no separate fields to copy or lose.
Passphrase or raw key
Type a passphrase (stretched with PBKDF2-HMAC-SHA256, 600,000 iterations) or paste an exact 128/192/256-bit key as hex or Base64, with a live byte-count badge that confirms the length.
OpenSSL-compatible output
Switch on OpenSSL mode to emit the Salted__ format that the openssl enc command and CryptoJS read, with the equivalent CLI command shown live so you can reproduce it in a terminal.
100% in your browser
Every byte is encrypted locally with the Web Crypto API. Open your Network tab and you will see nothing leave the page — it even works offline.
Base64 or Hex output
Copy the result in whichever encoding your target system expects, and inspect the salt, IV, ciphertext, and tag lengths in the segment breakdown strip.
AES Encryption Examples
GCM + passphrase (self-contained, non-deterministic)
The quick brown fox jumps over the lazy dog.
salt (16 B) + IV (12 B) + ciphertext + tag (16 B), Base64-encoded — a new value on every run
With Mode GCM, Key size 256, Key type Passphrase and the passphrase hunter2, this sentence encrypts to a single self-contained Base64 string. Encrypt it twice and you will get two completely different outputs — that is intentional. Passphrase mode generates a fresh 16-byte salt and a fresh 12-byte IV for every encryption, so identical plaintext never produces identical ciphertext and an observer cannot tell that two messages are the same. The segment strip under the output shows the exact layout: salt, then IV, then the ciphertext with its 128-bit GCM tag appended. To decrypt, the recipient needs only the passphrase and the same mode and key size — the salt, IV, and tag all travel inside the string.
OpenSSL-compatible output (CBC + passphrase)
Attack at dawn!
U2FsdGVkX18AESIzRFVmd1PBwxIFQpF+VgIhTK0aDHQ=
Switch on OpenSSL-compatible mode with Mode CBC, Key type Passphrase, the passphrase correct-horse, KDF PBKDF2 and 10,000 iterations. The tool then emits the OpenSSL Salted__ format: Base64 that always starts with U2FsdGVkX1, which is the Base64 encoding of the 8-byte Salted__ header. Because a fresh random 8-byte salt is generated each time, the exact string changes on every run, but every one decrypts on the command line with: echo 'U2FsdGVkX18AESIzRFVmd1PBwxIFQpF+VgIhTK0aDHQ=' | openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -pass pass:correct-horse -base64 -A — which prints Attack at dawn!. Choose EVP-MD5 instead of PBKDF2 to match CryptoJS or OpenSSL 1.0.2 and older. Note that openssl enc has no GCM support, so OpenSSL mode is CBC-only.
How to Encrypt Text with AES
- 1
Pick a mode and key size
Leave Mode on GCM (recommended) and Key size on 256 for the strongest sensible default. Switch to CBC or CTR only if a system you are targeting requires it.
- 2
Choose passphrase or raw key
Keep Key type on Passphrase and enter a strong passphrase, or switch to Raw key and paste an exact 128/192/256-bit key as hex or Base64. The byte-count badge confirms whether your raw key is a valid length.
- 3
Enter the text to encrypt
Type or paste your plaintext. Encryption runs automatically as you type, entirely in your browser — no button round-trip and no upload.
- 4
Copy the self-contained ciphertext
The Base64 result on the right already contains the salt, IV, and authentication tag. Use the segment strip to see the byte layout, then click Copy. Switch the output encoding to Hex if your target system expects it.
- 5
Decrypt it back when you need to
Give the ciphertext, the passphrase, and the same mode and key size to the recipient, or open the AES decrypt page to reverse it yourself.
Common AES Encryption Mistakes
Confusing a passphrase with a raw key
A raw key must be exactly 16, 24, or 32 bytes of random data (entered as hex or Base64); a passphrase is any text and must be stretched by a KDF first. Selecting Raw key and pasting a human passphrase either errors on length or produces a weak key.
Key type: Raw key Key (hex): correct horse battery staple (not hex, not 32 bytes)
Key type: Passphrase Passphrase: correct horse battery staple (stretched with PBKDF2)
Reusing an IV with the same key
The IV must be unique per message under a given key. Reusing it is fatal for GCM (it can leak the authentication key) and breaks confidentiality for CBC and CTR. Let the tool generate a fresh random IV every time.
// same key, same IV for two messages encrypt(key, iv, a); encrypt(key, iv, b);
// fresh random IV each time (the default) encrypt(key, randomIV(), a);
Losing the salt, IV, or tag
If you copy only the ciphertext bytes and drop the prepended salt/IV — or the appended GCM tag — the data can never be decrypted. Keep the whole self-contained string, not just the middle of it.
stored = ciphertext // salt + IV + tag thrown away
stored = salt + iv + ciphertext + tag // the full Base64 string
Expecting GCM output to match every run
GCM (and passphrase mode generally) uses a random salt and IV, so the same text encrypts to a different Base64 string every time. That is a security feature, not a bug — it means an eavesdropper cannot tell that two ciphertexts encrypt the same message.
assert(encrypt(msg) === encrypt(msg)) // fails — and should
assert(decrypt(encrypt(msg)) === msg) // this is what must hold
What You Can Do with AES Encryption
- Learn how AES modes behave
- Flip between GCM, CBC, and CTR with the same input to see how authentication, IV length, and ciphertext size change. A hands-on way to understand what NIST SP 800-38D actually specifies.
- Produce ciphertext another system can read
- Generate output in the OpenSSL Salted__ format (or as a raw key plus IV) so a backend, script, or teammate using openssl or a crypto library can decrypt it without friction.
- Encrypt a short note or snippet
- Protect a one-off piece of personal text — a recovery phrase you are moving between devices, a snippet in a support ticket — with a passphrase only you know. Not for regulated or production secrets.
- Prototype an encryption format
- Nail down your salt/IV/tag layout and KDF settings here before writing the code, using the segment breakdown to confirm the byte order and lengths.
- Generate test vectors
- Create known ciphertext with a fixed passphrase and mode to feed your own decryption tests, then verify the round-trip on the AES decrypt page.
AES Modes & Key Derivation
- GCM (Galois/Counter Mode) — authenticated, recommended
- Confidentiality plus a 128-bit authentication tag (NIST SP 800-38D). It uses a 96-bit (12-byte) IV, generated randomly per encryption, and both encryption and decryption parallelize well. The one rule you must never break: never reuse an IV with the same key. SP 800-38D limits a single key to about 2^32 randomly generated IVs, and a repeat leaks the XOR of two plaintexts and can even expose the authentication key that protects the tag. Best for almost everything.
- CBC (Cipher Block Chaining) — confidentiality only
- Each block is XORed with the previous ciphertext block, using a random 16-byte IV. It has no built-in authentication, so it must be paired with a separate MAC — encrypt-then-MAC, for example with our HMAC generator — and it is historically prone to padding-oracle attacks (Vaudenay, EUROCRYPT 2002). Offered here for interoperability with OpenSSL and older systems.
- CTR (Counter) — confidentiality only, stream-like
- Turns AES into a stream cipher by encrypting a counter, so any byte length works without padding and blocks parallelize freely. Like CBC it provides no integrity on its own, and reusing the counter/IV under one key is catastrophic. Useful when you need random access or streaming semantics.
- ECB — not offered (by design)
- Electronic Codebook encrypts each block independently, so identical plaintext blocks produce identical ciphertext and patterns leak — the notorious 'ECB penguin'. The Web Crypto API deliberately does not implement it, and neither do we. If a legacy peer requires ECB, treat that as a bug to fix rather than a format to reproduce.
- Key derivation: 600,000 vs 10,000 vs 1 iteration
- In the default passphrase mode this tool uses PBKDF2-HMAC-SHA256 at 600,000 iterations (the same SHA-256 hash applied hundreds of thousands of times) with a 16-byte salt, per OWASP. In OpenSSL-compatible mode, PBKDF2 defaults to just 10,000 iterations (the openssl enc default), and the legacy EVP_BytesToKey KDF used by CryptoJS and old OpenSSL runs a single MD5 pass — orders of magnitude weaker. More iterations mean a slower brute-force per guess, which is why the modern default is so much higher. Argon2 and scrypt are stronger still but are not part of Web Crypto, so they are out of scope here; for password storage, follow OWASP and prefer Argon2id.
AES Encryption Best Practices
- Prefer GCM unless a peer requires otherwise
- Authenticated encryption catches tampering that CBC and CTR silently pass through. Only drop to CBC or CTR for interoperability, and add a MAC if you do.
- Use a fresh random IV for every message
- The tool does this automatically. If you override the IV manually, never reuse one with the same key — for GCM a repeat is catastrophic, and for CBC it breaks semantic security.
- Choose strong passphrases and real random keys
- PBKDF2 slows brute force but cannot rescue a weak passphrase. Generate a long passphrase with the password generator, or a true random key with the secret key generator.
- Keep the salt, IV, and tag with the ciphertext
- They are not secret, but decryption fails without them. This tool's self-contained format bundles all three; if you use raw-key bare-ciphertext mode, copy the IV separately and store it alongside the ciphertext.
- Do not encrypt production or regulated secrets in any online tool
- Even fully client-side, a browser tool is for learning, debugging, and personal one-offs. Real secrets belong in a vetted key-management system with audited key handling and rotation. AES-256 itself is strong — approved under the NSA CNSA 2.0 suite for information up to TOP SECRET — and real-world breaks come from implementation mistakes, not the cipher.
AES Encryption FAQ
Is it safe to encrypt text online?
Can AES be decrypted without the key?
GCM vs CBC — which mode should I use?
AES-128 vs AES-256 — is 256 worth it?
Is my data uploaded when I encrypt here?
What is the difference between a passphrase and a key?
Can I encrypt so OpenSSL or CryptoJS can decrypt it?
Related Tools
View all tools →AES Decryption Tool — OpenSSL & CryptoJS Compatible
Security Tools
Decrypt AES online — GCM/CBC/CTR, passphrase or raw key, auto-detects OpenSSL & CryptoJS "U2FsdGVkX1" format. 100% in-browser, keys never leave the page.
Bcrypt Hash Generator & Verifier
Security Tools
Generate and verify bcrypt password hashes online — adjustable cost, $2b$/$2a$/$2y$ prefixes. 100% in your browser; your password is never uploaded.
HMAC Generator & Signature Verifier
Security Tools
Free online HMAC generator & verifier — compute or verify HMAC-SHA256/SHA1/384/512 with Text, Hex or Base64 keys and Hex/Base64/Base64URL output. 100% in your browser; your secret key never leaves the page.
JWT Decoder
Security Tools
Decode JWT tokens online with our free JWT decoder. Instantly inspect header, payload, signature, expiration, algorithm, and claims. 100% browser-based — your token never leaves your device. No signup, no tracking.
JWT Encoder & Generator
Security Tools
Free online JWT generator & encoder. Build the header and payload, sign with HS256, RS256, or ES256 instantly. 100% in-browser — your secret and key never leave your device.
Free JWT Secret Generator — HS256/384/512
Security Tools
Generate a strong, RFC-correct JWT secret for HS256/384/512 — 100% in your browser, never sent to a server. base64url, base64 or hex; copy for .env.