Skip to main content

How to Encrypt Text with AES and a Passphrase (AES-256-GCM, Done Right)

Encrypt text with a password using AES-256-GCM in your browser. What the key, IV, and salt do, why GCM is the modern default, and when to use it.

Published By Li Lei
#aes #encryption #webcrypto #security #privacy

How to Encrypt Text with AES and a Passphrase (AES-256-GCM, Done Right)

Sometimes you have one short secret to move from here to there — a database connection string, a recovery code, an API key you don't want sitting in plaintext on someone else's server. Setting up PGP keys for a single message is overkill. What you actually want is to scramble a piece of text with a password, send the scrambled blob, and let the other person unscramble it with the same password.

That's exactly what AES encryption with a passphrase does. The AES Text Encryptor handles it without a server, an account, or a single byte leaving your browser tab. This post walks through how it works, what the moving parts actually do, and — just as important — what this kind of tool is not meant for.

Why AES-GCM is the modern default

AES is the block cipher, but a cipher alone isn't a complete recipe. You also have to pick a mode — the way the cipher is applied across a whole message. Older code reaches for AES-CBC, which gives you confidentiality (the content is hidden) but nothing else. CBC has a long history of footguns, the padding oracle attack being the famous one, where an attacker who can submit altered ciphertext and watch how the system responds can slowly peel the plaintext back out.

AES-GCM (Galois/Counter Mode) closes that gap. It does two jobs at once: it encrypts the content and it authenticates it. After encrypting, GCM appends a 128-bit authentication tag. When you decrypt, the algorithm recomputes that tag and checks it. If the password is wrong, or if even a single byte of the ciphertext was flipped in transit, decryption doesn't hand you back corrupted-but-plausible text — it throws an error and refuses. That "fail loudly" behavior is the whole reason authenticated encryption is the recommended default for new code. You find out something is wrong instead of trusting garbage.

What the key, IV, and salt actually do

A passphrase like correct horse battery staple is not a cryptographic key. It's too short, too structured, and not the fixed 256-bit length AES expects. Three pieces bridge the gap between a human password and real encryption, and it's worth knowing what each one is for.

  • The salt is a random value generated fresh every time you encrypt. It's mixed into the password before the key is derived, so the same password produces a different key on every run. That stops an attacker from precomputing one giant table of "password → key" mappings and reusing it against everybody.
  • The key is what AES actually encrypts with. It's derived from your passphrase and the salt using PBKDF2 (Password-Based Key Derivation Function 2) with SHA-256, run for 250,000 iterations. The iteration count is deliberate friction: it makes each password guess slow, so brute-forcing a stolen ciphertext costs an attacker real time per attempt.
  • The IV (initialization vector) is a random 12-byte value generated per message. It guarantees that encrypting the same plaintext with the same key twice produces different ciphertext, so an observer can't tell that two blobs contain the same secret.

Here's the concrete version of the whole flow, which is the one fact worth carrying away: AES-GCM derives a key from your passphrase with a salt, encrypts with a random IV, and outputs ciphertext you can only decrypt with the same passphrase. The salt and IV aren't secret — they're packed right alongside the ciphertext — but the passphrase is, and without it the math doesn't reverse.

A worked example: encrypting a note

Say you want to send a teammate a recovery code, RECOVERY-7F3A-9K2D, and you'll tell them the password over a phone call so it never travels with the message.

You paste the note in, type a passphrase like bluefin-coral-lantern-92, and hit Encrypt. The output is a single Base64 string — something along the lines of:

k4hN2pQ7vR1sT8xL5mB3cA6dE9fG0wU...iZ==

That opaque blob is actually three things glued together and Base64-encoded: the 16-byte salt, the 12-byte IV, and the AES-256-GCM ciphertext (with its authentication tag). Because it's self-describing, the person decrypting only needs two things — the string and the password. No separate key file to ship around, no setup.

They paste the blob in, type bluefin-coral-lantern-92, hit Decrypt, and get RECOVERY-7F3A-9K2D back. If they fat-finger the password, or if a single character of the blob got mangled when it was copied, GCM's tag check fails and they see an error instead of a wrong code. That refusal is a feature.

It's a different thing from Base64 encoding, which often confuses people. Base64 is reversible by anyone with no password — it hides nothing. The blob above looks like gibberish, but the gibberish only stays secret because of the AES layer underneath, not the Base64 wrapping on top.

Everything stays local — the secret never leaves your browser

This is the part I care about most, and it's worth being blunt about. The entire operation runs in your browser through the native WebCrypto API. There is no server in the loop. Your plaintext, your password, and your ciphertext are never uploaded, never logged, and never seen by anyone — including me. All the randomness for the salt and IV comes from crypto.getRandomValues, the browser's cryptographically secure generator.

I built it to deliberately not save anything to localStorage and to never write your input into the URL. For most Toolora tools I do the opposite — I want a shared link to carry your inputs so the result travels with it. For a tool that handles secrets, that would be exactly wrong. So there's no history here, and nothing to recover if you close the tab. That's the correct trade-off: the only shareable thing is the empty tool page, not your data.

If you want to verify the same idea applies to other client-side primitives, the same local-only model runs the hash generator and the password generator — none of them phone home.

This is casual protection, not a key-management system

Be honest with yourself about what this tool is. The cryptography underneath is solid — AES-256-GCM and PBKDF2-SHA256 are standard, well-audited primitives running through the browser's vetted implementation. The weak points are not the math. They're you and where the ciphertext lands.

Two failure modes account for almost every real-world break:

  1. Weak passwords. PBKDF2's 250,000 iterations slow an offline attacker down, but they can't rescue a six-character password. Once someone has your ciphertext, they grind guesses on their own hardware at their own pace. For anything valuable, use a long, random passphrase — generate one with the password generator if you don't trust yourself to invent one.
  2. Leaking the password alongside the ciphertext. Encryption protects the content, but the password is the keystone. Don't send the password in the same email as the blob. Don't store the two together. Doing either defeats the entire exercise.

And know the boundary. This is for one-off secrets and casual protection — a note you don't want a notes-app breach to expose, a code you'd rather not paste in cleartext. It is not a password manager, a key vault, or an infrastructure secrets system. There's no rotation, no access control, no recovery if you forget the password (that's by design — there's no backdoor). If you're hashing passwords for storage, you want bcrypt instead, which is built for that specific job. Match the tool to the threat, and AES text encryption does a clean, honest job within its lane.


Made by Toolora · Updated 2026-06-13