Encrypt and Decrypt Text with a Passphrase
Type a message, pick a passphrase, and you get a base64 block that only the same passphrase can open. The key is derived on your device with PBKDF2 and the encryption is AES-256-GCM, so a modified block fails to decrypt rather than quietly producing garbage.
The key comes from this passphrase and nothing else. There is no reset link and no recovery: if you forget it, the text is gone for good.
What happens when you press Encrypt
Four steps, all of them in your browser's Web Crypto implementation rather than in JavaScript:
- Sixteen random bytes are drawn as a salt, and twelve more as the IV — the nonce AES-GCM needs.
- Your passphrase is stretched into a 256-bit key with PBKDF2-HMAC-SHA-256, 250,000 rounds, using that salt.
- The text is encoded as UTF-8 and encrypted with AES-256-GCM, which produces the ciphertext plus a 16-byte authentication tag.
- The salt, the IV, the round count and the ciphertext are packed together and base64-encoded, so the whole thing survives being pasted into an email.
Decryption reads the parameters back out of the block, so you only ever need the passphrase.
The output format, byte by byte
Nothing here is proprietary, and a format you cannot open elsewhere is not much of a safeguard. After base64-decoding the block you get:
- Byte 0 — format version, currently
1. - Bytes 1 to 4 — the PBKDF2 round count, 32-bit big-endian.
- Bytes 5 to 20 — the 16-byte salt.
- Bytes 21 to 32 — the 12-byte GCM nonce.
- Byte 33 onward — the AES-256-GCM ciphertext with its 16-byte tag appended, which is the layout Web Crypto produces.
The round count travels with the block so that the number can be raised later without breaking anything encrypted today. On the way back in it is range-checked, because otherwise a block from a stranger could ask your browser to run a billion rounds and hang the tab.
Why the same text gives a different block every time
A fresh salt and a fresh nonce are generated for every message, so encrypting the same sentence twice with the same passphrase produces two unrelated blocks. That is the correct behaviour. Identical output would tell an observer that two messages are the same without them reading either.
It also matters that the nonce is never reused with the same key. GCM is unusually brittle here: repeat a nonce and an attacker can recover the XOR of two plaintexts and, worse, derive the value used to authenticate messages, which lets them forge blocks. Random nonces per message, with a fresh key derived from a fresh salt, keep this well away from the danger zone.
Why GCM rather than CBC
Most "AES encryption" tools use AES-CBC with no authentication. Encryption alone hides the content but does not detect changes: flip bits in a CBC ciphertext and it still decrypts, into something different, with no complaint. That is the door padding-oracle attacks walk through. GCM produces an authentication tag alongside the ciphertext, so a single altered byte makes decryption fail outright. If you see "Could not decrypt", the block genuinely did not verify.
Where this falls short
The passphrase is the whole thing. PBKDF2 at 250,000 rounds makes each guess cost real work, but an attacker with the block guesses offline, in parallel, on hardware built for it, for as long as they like. A word from a dictionary with a number after it will not survive that. Four or five genuinely random words will.
PBKDF2 is the weakest of the modern choices. Argon2 and scrypt are memory-hard, which blunts the GPU advantage; PBKDF2 is not, and a GPU attacker gets much better value against it. Browsers only expose PBKDF2 through Web Crypto, and pulling in an Argon2 build is exactly the kind of dependency this site does not ship. That is a real limitation, not a preference.
It proves integrity, not identity. A block that decrypts was not modified by anyone without the passphrase. It does not prove who wrote it, because anyone holding the passphrase can write one. For messages between people, tools built for that — age, GPG, Signal — do the part this cannot.
Text only. There is no file mode. Encrypting a file means reading it wholly into memory and handing you a download, and for anything sizeable a desktop tool does it better.
Two practical notes. Sending the passphrase through the same channel as the block defeats the exercise entirely. And the result passes through your clipboard, which other applications on the machine can often read.
Frequently asked questions
Is this actually secure?
The cryptography is standard and runs in the browser native implementation: AES-256-GCM with a key stretched from your passphrase by PBKDF2-HMAC-SHA-256 over 250,000 rounds with a random salt. The weak point is never the algorithm, it is the passphrase. A short or guessable one can be brute-forced offline no matter how good the cipher is.
What happens if I forget the passphrase?
The text is unrecoverable. There is no key escrow, no reset and no copy of anything anywhere — the page holds no state and there is no server behind it. Write the passphrase down somewhere before you rely on the block.
Why does encrypting the same text twice give different output?
Because a new random salt and nonce are generated each time. Identical ciphertext would leak the fact that two messages are identical, so this is a feature rather than a glitch.
Can I decrypt this with OpenSSL or Python?
Not with a single OpenSSL command, because the salt, nonce and round count live in a header of our own. The layout is documented above, and about ten lines of Python with the cryptography package will read it: slice the fields out, run PBKDF2, then open the rest with AES-GCM.
Can I encrypt a file instead of text?
Not here. This tool handles text only. For files, use age or GPG on the desktop, or a password-protected archive if the recipient has nothing else installed.
Last updated September 19, 2026