How do you use this tool?
- Paste plaintext in the top field, type your passphrase below (at least 12 characters recommended).
- Pick the algorithm — AES-256-GCM is the default and provides authenticated encryption.
- Pick the output format — Base64 (compact) or Hex (good for logs).
- Click 'Encrypt' — the ciphertext appears immediately below.
- To decrypt, switch to 'Decrypt' mode and paste ciphertext + the identical passphrase.
What does this tool do?
You type plaintext and a passphrase, the tool encrypts both with AES — symmetric, meaning the same key is used to decrypt. In Decrypt mode you reverse the process. Both operations run fully in your browser via the Web Cryptography API, a W3C-standardised interface every modern browser has shipped since roughly 2015. No server round-trip, no account, no tracking. You can load the page offline (PWA) and the tool keeps working.
Output as Base64 (compact, friendly for mail/chat) or Hex (friendly for logs and debug diffs). The output bundles three pieces back-to-back: a random salt for key derivation, a random initialisation vector (IV), and the ciphertext itself. The layout is documented explicitly so you can decrypt the ciphertext with OpenSSL, Python, or any other AES-capable stack.
Why browser AES and not just an online tool?
Three of the most-trafficked online AES tools — aesencryption.net, encryption-decryption.online, devglan.com — accept your plaintext and your passphrase and POST both over HTTPS to a server. The server encrypts and returns the ciphertext. That’s absurd: a cipher whose purpose is to keep the plaintext secret leaks the plaintext to a remote server before it computes anything. HTTPS protects the connection, not the server operator, not cloud-provider logs, not an attacker with server access.
Browser AES flips that. Your plaintext and your passphrase stay in the JavaScript context of your browser tab. They’re processed by the crypto.subtle API, which runs inside the browser engine — the same code path the browser uses for TLS handshakes. The ciphertext appears in the tab. You copy it, share it, the plaintext never travels.
Why these three algorithms, no more, no less?
AES-256-GCM is the default and recommendation. AES (Advanced Encryption Standard) was NIST-certified in 2001 (FIPS 197) and remains unbroken — no known practical method reduces the effective key strength below the brute-force bound. With a 256-bit key it stays comfortable even against Grover’s quantum algorithm, which would halve effective strength to a still-strong 128 bits. GCM (Galois/Counter Mode) adds an authentication tag — any tampering with the ciphertext is caught on decryption. Specification: NIST SP 800-38D.
AES-128-GCM is the faster variant with a 128-bit key. Still strong; sensible when raw speed matters on older hardware or embedded contexts. For most browser use-cases the speed difference is negligible.
AES-256-CBC is the classic mode without an authentication tag. PKCS#7 padding lets any plaintext length be encrypted. Important caveat surfaced in the tool: CBC will NOT detect ciphertext tampering. A single bit flip decrypts to junk without raising an error — dangerous when data is consumed without a separate checksum. We offer CBC only because many legacy systems (old Java apps, some IoT firmware) only support CBC. For new data: prefer GCM.
What we intentionally do not offer: AES-ECB (Electronic Codebook). ECB is cryptographically broken because identical plaintext blocks produce identical ciphertext, exposing plaintext patterns — the famous ECB-penguin demonstrates it: a Tux-on-Linux image encrypted with ECB still shows the penguin silhouette. Many online tools list ECB as an option, some as the default. We hard-block it.
How does PBKDF2 work and why do I need it?
A passphrase is not a key. A typical passphrase has 20–40 bits of entropy; AES wants 128 or 256 bits. Closing that gap is the job of a key derivation function (KDF) — it stretches the passphrase to the full key length and makes brute-force attempts expensive through many repeated hash operations.
We use PBKDF2 with SHA-256 as the hash function and 100,000 iterations. That matches the OWASP 2024 minimum recommendation for PBKDF2-HMAC-SHA-256. Every encryption generates a fresh random 16-byte salt that gets stored alongside the ciphertext. Salt prevents rainbow-table attacks: two users with the same passphrase end up with different keys.
There are more modern KDFs — Argon2 (winner of the 2015 Password Hashing Competition), scrypt (memory-hard) — that are even more resistant to GPU brute-force. The browser Web Crypto API doesn’t yet support Argon2 natively; it would require WebAssembly, which breaks our zero-dependency commitment. PBKDF2 with 100,000 SHA-256 iterations is sufficient for educational use.
What’s actually inside the output blob?
The ciphertext output is a concatenation of three components, Base64- or hex-encoded:
[salt:16 bytes][IV:12 bytes for GCM, 16 bytes for CBC][ciphertext (+16-byte auth tag for GCM):variable]
On decryption the tool reads the first 16 bytes as salt, the next 12 (or 16 for CBC) as IV, and treats the rest as ciphertext + optional auth tag. This layout convention isn’t NIST-standardised — different AES tools use different orderings. We document it explicitly so you can build interoperability yourself.
Decrypting externally with Python (cryptography library):
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
blob = base64.b64decode("YOUR_BASE64_OUTPUT")
salt, iv, ct = blob[:16], blob[16:28], blob[28:]
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000)
key = kdf.derive(b"YOUR_PASSPHRASE")
plaintext = AESGCM(key).decrypt(iv, ct, None)
print(plaintext.decode("utf-8"))
OpenSSL CLI does not directly cover this layout via openssl enc because OpenSSL uses its own salt prefix. For pure OpenSSL compatibility you would have to extract salt + IV manually and call openssl enc -K <hex> -iv <hex> — tedious. Python or Node are the ergonomic paths.
How safe is the passphrase, really?
The security of the whole encryption rests on the passphrase. AES-256 cannot be broken mathematically — but if the passphrase is ‘Secret123’, a GPU cracks it in hours regardless of cipher strength.
Rules of thumb for 2026:
- Fewer than 8 characters, one class (lowercase only): insecure; seconds to minutes to brute-force.
- 8–11 characters, mixed classes: hours to days against a modern GPU with 100,000 PBKDF2 iterations.
- 12–15 characters, mixed classes: weeks to months. Acceptable for low-threat use-cases.
- 16+ characters, mixed classes or Diceware pattern: years to decades. Recommended.
- Diceware with 6 words from a 7,776-word list: ~77 bits of entropy, practically unbreakable through brute force into the 2050s and beyond.
The strength indicator below the passphrase field is a rough heuristic (length + class mix), not a zxcvbn-level estimator. It flags obviously weak inputs in red, borderline in yellow, and gives green for solid length.
What does this tool deliberately not do?
Encrypt files. The MVP accepts text only. Bulk file encryption is a Phase-2 backlog item — it needs chunked reading + a progress UI + a download-blob handler. Workaround today: base64-encode small files (browser-built-in or our Base64 Encoder) and encrypt the base64 string.
Asymmetric crypto. That class (RSA, elliptic curves, PGP, age) has fundamentally different UX: a public and a private key, key management, a trust model. Separate tool if ever needed, not crammed into the AES tool.
Cloud storage for keys. Anti use-case. A cipher whose key lives on someone else’s server is a cloud database with extra steps.
Custom salt or custom IV. Foot-gun. Users would set static IVs and destroy the security guarantee. Intentionally not exposed.
Argon2 or scrypt as KDF alternatives. PBKDF2 is Web-Crypto-native. Argon2 would require WebAssembly (libsodium) and grow the bundle. Evaluate only once threat models actually demand it.
Educational use — what does that mean in practice?
This tool is built for educational and casual personal use: keep a short note secret, share a meeting point in a chat, encrypt an API phrase in a personal notebook, get hands-on with the AES concept. It is not built for:
- GDPR-/HIPAA-mandated encryption of personal data in business contexts — that requires certified hardware tokens, qualified signatures, documented key management with rotation and backup strategy.
- Defending against state-level actors or intelligence services — those threat models demand hardware security modules (HSMs), secure enclaves, air-gapped machines, protocol-level forward secrecy.
- Medical, financial, or legal compliance encryption — see HIPAA, PCI-DSS, eIDAS requirements.
For those use-cases the right tools are GnuPG (for file/mail encryption with web-of-trust), age (modern, slimmer), HashiCorp Vault or AWS-KMS equivalents (for server-side key management), or qualified signature services under eIDAS.
Educational use means: the tool is mathematically correct, it uses FIPS-validated primitives, output is interoperable with professional crypto stacks. But the threat-model assumptions — passphrase in your head, no HSM, no audit log, no key-rotation workflow — only suit low-threat contexts.
How does Web Crypto behave across browser versions?
Stable and cross-browser since around 2017. Specifically:
- Chrome / Edge: since version 37 (2014).
- Firefox: since version 34 (2014).
- Safari (macOS / iOS): since Safari 11 / iOS 11 (2017).
The methods used here (crypto.subtle.encrypt, crypto.subtle.decrypt, crypto.subtle.deriveKey, crypto.subtle.importKey, crypto.getRandomValues) are all specified in the W3C Web Cryptography API Recommendation (2017) and fully implemented in every major browser. On mobile Safari iOS 11+ and Chrome Mobile the same holds. No polyfill, no fallback.
How do you verify the cipher really runs locally?
Open DevTools → Network tab (Cmd+Option+I on Mac, F12 on Windows), run an encryption — zero network requests fire. The service worker installs PWA caching, so the page loads offline and the AES still works. Component source is inspectable in the browser (Sources tab → AesVerschluesselungTool.svelte) — the crypto calls are directly traceable.
A second sanity check: in the DevTools Console, type crypto.subtle — you should see a SubtleCrypto object. That object’s methods are implemented in the browser engine itself (C++ in Chrome/Edge, in Rust + C++ in Firefox, in Swift/C++ in WebKit), not in JavaScript loaded from a CDN. When this tool calls crypto.subtle.encrypt(...), control flows directly into those native methods. The plaintext never traverses an fetch(), never lands in a request body, never gets serialised to a server somewhere.
Why does each encryption produce a different ciphertext?
Encrypt the same plaintext twice with the same passphrase, and the two outputs are completely different. That’s deliberate and important. Every call generates a fresh random 16-byte salt (which means a different derived key) and a fresh random 12- or 16-byte IV. Without that, an attacker observing two ciphertexts could detect that the plaintexts are identical — a metadata leak that destroys confidentiality for repeated messages.
The salt and IV are stored alongside the ciphertext (in the blob header). They’re not secret — the security guarantees of AES-GCM hold as long as the IV is unique per encryption under the same key, not as long as the IV is hidden. Reusing the same IV under the same key with GCM is a catastrophic break: it leaks the XOR of two plaintexts and allows authentication-tag forgery. The random per-call IV in this tool is the single most important defence against that footgun.
What happens if I tamper with the ciphertext?
For AES-GCM (default), the tool catches it. The Galois/Counter Mode appends a 16-byte authentication tag to every ciphertext. On decryption, the tag is recomputed from the ciphertext + IV + key and compared. If the ciphertext, IV, or key are wrong by even one bit, the recomputed tag doesn’t match, and the API throws an OperationError — surfaced as ‘Decryption failed’ in the UI. You cannot get plaintext-shaped output by flipping ciphertext bits.
For AES-CBC, tampering goes undetected. Flip a bit, decrypt, and you get plaintext-shaped junk for that block plus a usable bit-flip in the next block (CBC bit-flipping attack). This is exactly why GCM exists and why we mark CBC as legacy. If you absolutely must use CBC (interop with old systems), pair it with a separate HMAC over the ciphertext — but at that point you’re building Encrypt-then-MAC manually, and you’d be better off just using GCM.
Who actually needs this in everyday life?
- Developers who want to share an API phrase, a meeting point, or a test token in mail or Slack DM without setting up a PGP key exchange first.
- Teachers and students in cryptography courses, walking through AES hands-on: what changes when I tweak the passphrase, how do IV variations look, what does PKCS#7 padding actually do.
- Journalists with low-threat source contacts who want to forward a short note from a research notebook over email.
- Private users with a notebook full of passwords who want to back the notebook up to the cloud, with plaintext staying offline and ciphertext travelling to iCloud / Dropbox / Drive.
In every case: this tool is a tier above ‘plaintext in the cloud’ and a tier below ‘GnuPG workflow with HSM’. It fills a gap that server-roundtrip online tools simply cannot fill.
Frequently Asked Questions
The key answers live in the FAQ block above — they’re emitted as structured FAQPage JSON-LD for search engines.
Which tools Are Related?
More tools from the kittokit ecosystem that fit the same context:
- Hash Generator — compute MD5 / SHA-1 / SHA-256 / SHA-384 / SHA-512 hashes of text, fully in the browser.
- Password Generator — generate strong random passphrases, perfect for AES keys.
- JWT Decoder — decode JWTs without a server round-trip.
Last updated: