AES Decryption Tool — OpenSSL & CryptoJS Compatible
Decrypt AES online — GCM/CBC/CTR, passphrase or raw key, auto-detects OpenSSL & CryptoJS "U2FsdGVkX1" format. 100% in-browser, keys never leave the page.
Advanced options
Never reuse an IV with the same key. Leave blank to generate a secure random IV.
How AES Decryption Works
AES decryption is the exact inverse of encryption: the same symmetric key that scrambled the data runs the cipher's rounds in reverse to recover the original bytes. Because AES is symmetric, there is no separate 'decrypt key' — you must supply the identical key or passphrase, mode, and IV that were used to encrypt. Get the parameters right and the plaintext comes back byte-for-byte; get one wrong and you get an error or garbage.
To decrypt correctly, four things must match the encryption exactly: the key (or the passphrase plus its key-derivation settings), the mode of operation (GCM, CBC, or CTR), the IV or nonce, and — for GCM — the authentication tag. Miss any of them and the result is either a hard error (a GCM authentication failure, a CBC padding failure) or silent garbage (CTR, or CBC with the wrong IV). This tool reads the salt, IV, and tag out of the ciphertext for you when they are packed in, and diagnoses the failure when something does not line up.
Ciphertext arrives in a few different shapes, and this tool understands three. Format 1 is our self-contained passphrase layout: a 16-byte salt, then the IV, then the ciphertext (with the GCM tag appended in GCM mode) — decrypt it with only the passphrase. Format 2 is the raw-key layout: the IV prepended to the ciphertext, or 'bare' ciphertext where you supply the IV separately. Format 3 is the OpenSSL layout, produced by the openssl enc command and by CryptoJS.
That OpenSSL format is worth knowing by sight. It begins with the 8 ASCII bytes Salted__, followed by an 8-byte salt and then the ciphertext, and when the whole thing is Base64-encoded those first bytes always render as the prefix U2FsdGVkX1. So if a ciphertext you were handed starts with U2FsdGVkX1, it was almost certainly produced by openssl enc or a CryptoJS AES.encrypt(text, passphrase) call. CryptoJS derives its key with the legacy EVP_BytesToKey function using a single MD5 pass, while modern openssl uses PBKDF2 — which is why picking the right key-derivation function is the whole game when decrypting these. If your input is Base64 and you just want to see the raw bytes, our Base64 decoder will show them. To create ciphertext in these formats, use the AES encryption tool.
// AES-256-GCM decrypt 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 aesGcmDecrypt(base64, passphrase) {
const enc = new TextEncoder();
const packed = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
const salt = packed.slice(0, 16), iv = packed.slice(16, 28); // salt(16) | iv(12)
const ct = packed.slice(28); // ciphertext + tag
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, ['decrypt']);
const plain = await crypto.subtle.decrypt(
{ name: 'AES-GCM', iv }, key, ct); // throws if the tag fails
return new TextDecoder().decode(plain); // recovered plaintext
} Key Features
Auto-detects OpenSSL & CryptoJS output
Paste ciphertext beginning U2FsdGVkX1 and the tool recognizes the Salted__ format and offers a one-click switch to the matching decrypt flow, so you never fight a dead-end error.
Three key-derivation functions
Decrypt across every generation of the openssl enc format: PBKDF2 with a custom iteration count, EVP_BytesToKey with SHA-256, or the legacy MD5 single-pass that CryptoJS uses.
Explains why decryption failed
Instead of a generic error you get a diagnosis: wrong key versus wrong IV, a GCM authentication failure, a CBC padding error, base64 pollution, or 'this looks like an MD5-era ciphertext, try EVP-MD5'.
Equivalent openssl command shown live
See the exact openssl enc -d command that reproduces the decryption on the command line, iteration count and all, so you can verify the result outside the browser.
Passphrase or raw key, GCM/CBC/CTR
Handles self-contained passphrase ciphertext, raw-key ciphertext with a prepended or separately supplied IV, and all three Web Crypto modes.
100% in your browser
Ciphertext and keys are processed locally with the Web Crypto API and never uploaded — you can verify with the Network tab or by going offline.
AES Decryption Examples
Decrypt a self-contained passphrase ciphertext (GCM)
salt(16) ‖ iv(12) ‖ ciphertext ‖ tag(16), Base64 — from the encrypt page
The quick brown fox jumps over the lazy dog.
This is the reverse of the encrypt page's GCM example. Take the self-contained Base64 string it produced for the passphrase hunter2, paste it here with Mode GCM, Key size 256, Key type Passphrase and the same passphrase hunter2, and the original sentence comes back. You do not enter a salt or IV separately — the tool reads the 16-byte salt and 12-byte IV from the front of the string, derives the key with PBKDF2-HMAC-SHA256 (600,000 iterations), and verifies the appended 128-bit GCM tag before returning any text. Click Load example on the encrypt page to generate a fresh string, then decrypt it here.
Decrypt real OpenSSL / PBKDF2 output
U2FsdGVkX18AESIzRFVmd1PBwxIFQpF+VgIhTK0aDHQ=
Attack at dawn!
This is genuine openssl enc output. Paste it in, switch to OpenSSL mode (Mode CBC, Key type Passphrase), enter the passphrase correct-horse, choose the PBKDF2 key-derivation function, and set iterations to 10,000 — the plaintext is Attack at dawn!. The U2FsdGVkX1 prefix told the tool this was Salted__ format, and the 8-byte salt sits right after that header inside the Base64. You can reproduce the exact decryption on the command line: echo 'U2FsdGVkX18AESIzRFVmd1PBwxIFQpF+VgIhTK0aDHQ=' | openssl enc -d -aes-256-cbc -pbkdf2 -iter 10000 -pass pass:correct-horse -base64 -A. If a similar ciphertext fails with PBKDF2, it was likely made by CryptoJS — switch the KDF to EVP-MD5 and try again. Click Load OpenSSL example to fill these values automatically.
How to Decrypt AES Ciphertext
- 1
Paste the ciphertext
Drop your Base64 or Hex ciphertext into the input. If it begins with U2FsdGVkX1, the tool flags it as OpenSSL/CryptoJS format and offers to switch you to the right mode.
- 2
Set the format and mode
For a self-contained string from this tool, keep Passphrase mode and the matching GCM/CBC/CTR. For OpenSSL/CryptoJS output, accept the switch (CBC + passphrase). For raw-key data, choose Raw key and the encoding, and supply the IV if it is not prepended.
- 3
Choose the key-derivation function
In OpenSSL mode, pick PBKDF2 (and its iteration count), EVP-SHA256, or EVP-MD5 to match how the key was derived. EVP-MD5 is the one CryptoJS uses.
- 4
Enter the passphrase or key
Type the exact passphrase, or paste the exact raw key as hex or Base64. The plaintext appears on the right as soon as everything matches.
- 5
Read the diagnosis if it fails
If decryption errors, the panel names the likely cause — wrong IV, wrong key, padding error, base64 pollution, or a KDF mismatch — so you can adjust one setting at a time instead of guessing.
Why AES Decryption Fails — and How to Fix It
GCM authentication failed
GCM refuses to return plaintext if the tag does not verify. The cause is a wrong passphrase or key, the wrong mode, a wrong IV, or altered/truncated ciphertext — GCM cannot say which. Recheck each against how the data was encrypted.
mode: CBC // but the data was encrypted with GCM => Authentication failed
mode: GCM, same passphrase and key size as encryption => plaintext
CBC: a garbled first block means the wrong IV
In CBC the IV only affects the first 16-byte block. If block one is garbage but the rest decodes cleanly, your IV is wrong; if everything is garbage, the key is wrong.
iv: 00000000000000000000000000000000 (wrong IV) => first block corrupt, rest readable
iv: (the exact IV used to encrypt) => Attack at dawn!
CBC / PKCS#7 padding error
A padding error almost always means the key is wrong; it can also mean the ciphertext was corrupted, truncated, or was not PKCS#7-padded. Confirm the full ciphertext was copied and that the passphrase and KDF match.
passphrase: hunter3 // one character off => padding error
passphrase: hunter2 // exact => plaintext
Base64 (or hex) pollution
Newlines, spaces, or smart quotes pasted along with the ciphertext break decoding. The tool strips whitespace automatically, but missing or extra characters still fail.
“U2FsdGVkX1...” (curly quotes and trailing junk copied in)
U2FsdGVkX18AESIzRFVmd1PBwxIFQpF+VgIhTK0aDHQ= (clean Base64)
U2FsdGVkX1 detected but OpenSSL mode is off
If the input starts with U2FsdGVkX1 you are looking at OpenSSL/CryptoJS Salted__ output, which will not decrypt as a normal passphrase string. The tool shows a banner; click Switch to OpenSSL mode and pick the KDF.
OpenSSL compatible: off input: U2FsdGVkX1... => cannot parse
OpenSSL compatible: on, KDF chosen => plaintext
KDF mismatch (the CryptoJS trap)
A ciphertext that fails with PBKDF2 or SHA-256 but decrypts with EVP-MD5 was produced by CryptoJS or openssl 1.0.2 and earlier. On the command line those need -md md5.
KDF: PBKDF2 // CryptoJS ciphertext => padding error
KDF: EVP-MD5 // matches CryptoJS => plaintext
What You Can Do with AES Decryption
- Decrypt openssl enc output
- Read a Salted__ blob produced by openssl enc -aes-256-cbc without dropping to a terminal: paste the Base64, enter the passphrase, pick the KDF, and get your plaintext.
- Decrypt CryptoJS ciphertext
- Recover data from a legacy app that used CryptoJS AES.encrypt(text, passphrase). Select EVP-MD5 to match its single-pass MD5 key derivation — the step most people miss.
- Debug a decryption that keeps failing
- When your own code cannot decrypt something, paste it here to isolate whether the problem is the key, the IV, the mode, the encoding, or the KDF, using the diagnosis panel.
- Verify an encryption round-trip
- Confirm that ciphertext from the AES encrypt page or from your app decrypts back to the exact original bytes.
- Understand an unknown ciphertext
- Identify a format from its shape — a U2FsdGVkX1 prefix, or a fixed-length prefix that looks like an IV — and work out how it was produced before you try a key.
AES Decryption Internals & Formats
- GCM decryption — authenticated
- GCM recomputes the 128-bit tag over the ciphertext and compares it before returning any plaintext; a mismatch throws instead of leaking corrupted data. It uses the 96-bit IV that was prepended. A GCM failure means the key, mode, IV, or ciphertext is wrong — the cipher cannot tell you which, only that authentication failed.
- CBC decryption — watch the first block and the padding
- CBC has two distinct failure signatures. If only the first 16-byte block is garbled and the rest looks right, the IV was wrong. If every block is garbage, the key is wrong. A PKCS#7 padding error usually means the key is wrong, or the ciphertext was corrupted or truncated. CBC has no tag (unlike an authenticated construction such as an HMAC), so a wrong key can even decrypt to plausible-looking bytes.
- CTR decryption — silent on error
- CTR never throws: a wrong key simply yields garbage, which usually surfaces as a 'not valid UTF-8' error once the bytes are decoded to text. Match the counter/IV exactly. Because there is no integrity check, treat any CTR output you did not authenticate separately with suspicion.
- Ciphertext layouts (F1 / F2 / F3)
- Format 1 (passphrase) is salt(16) then IV then ciphertext, with the 16-byte GCM tag appended in GCM mode. Format 2 (raw key) is IV then ciphertext, or bare ciphertext with a separately supplied IV. Format 3 (OpenSSL) is the ASCII header Salted__ then an 8-byte salt then ciphertext. Knowing which layout you have tells the tool where the salt and IV live, and a raw key itself should come from a CSPRNG — see the secret key generator.
- Key derivation: matching what encrypted the data
- For self-contained passphrase ciphertext this tool uses PBKDF2-HMAC-SHA256 at 600,000 iterations. For OpenSSL/CryptoJS ciphertext you must select the KDF that was used: PBKDF2 (the openssl -pbkdf2 default is 10,000 iterations — set your exact count), EVP_BytesToKey with SHA-256 (openssl 1.1+ without -pbkdf2), or EVP_BytesToKey with MD5 and a single pass (CryptoJS and openssl 1.0.2 and earlier). The classic 'it will not decrypt' bug is a CryptoJS or old-openssl ciphertext tried with SHA-256 — switch to EVP-MD5 and it works.
AES Decryption Best Practices
- Start by identifying the format
- Before touching settings, look at the ciphertext. A U2FsdGVkX1 prefix means OpenSSL/CryptoJS; a self-contained string from this tool is passphrase format; a bare blob usually needs a raw key and a separate IV.
- Match the key-derivation function exactly
- For OpenSSL/CryptoJS ciphertext the KDF is as important as the passphrase. If PBKDF2 fails, try EVP-MD5 (CryptoJS, old openssl); the iteration count must match too, not just the algorithm.
- Paste the ciphertext cleanly
- Stray newlines or spaces from copying can corrupt Base64. This tool strips whitespace, but if decoding still fails, check for smart quotes, missing characters, or a truncated copy. Our Base64 tool can help you inspect a suspect string.
- Treat a wrong-key result honestly
- With CTR or CBC a wrong key can produce bytes rather than an error. If the output looks like garbage or fails the UTF-8 check, the key or IV is wrong — do not trust partial-looking output.
- Never send secret ciphertext or keys to a server
- The point of decrypting in the browser is that nothing leaves the page. Avoid tools that upload; this one uses Web Crypto locally, and you can verify with the Network tab or by going offline. AES-256 is strong — CNSA 2.0-approved for TOP SECRET — so if you cannot decrypt, the problem is the parameters, not the cipher.
AES Decryption FAQ
Can you decrypt AES without the key?
How do I decrypt openssl enc output?
What does U2FsdGVkX1 at the start of a ciphertext mean?
How do I decrypt CryptoJS ciphertext?
GCM vs CBC — why does my ciphertext decrypt one way and not the other?
Is my ciphertext or key uploaded when I decrypt here?
What is the difference between a passphrase and a raw key when decrypting?
Related Tools
View all tools →AES Encryption Tool — GCM, CBC & CTR
Security Tools
Free online AES encryption — AES-128/192/256, GCM/CBC/CTR, passphrase (PBKDF2) or raw key. Runs 100% in your browser; nothing is uploaded.
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.