Secure Note Encrypter
AES-256-GCM encryption in your browser β zero server, zero logs
Why "Encrypted Links" Are Not Actually Encrypted (And What Real Browser-Side Encryption Looks Like)
Most people who share sensitive information over the internet are doing so with far less protection than they assume. A link that says "private" in a URL is not encrypted. A password-protected PDF is typically protected with algorithms that crumble under a dictionary attack in minutes. Even services that advertise end-to-end encryption often hold the keys themselves β which means they can read your data, and so can anyone who compels them legally to hand it over. The gap between what users believe about privacy and what cryptography actually guarantees is enormous, and it matters in everyday situations: sharing Wi-Fi passwords, sending medical information to a family member, coordinating credentials between remote workers.
The fundamental issue is trust in infrastructure. Whenever your message passes through a server β to be stored, relayed, or processed β that server is a potential point of exposure. It might log your data. It might be breached. It might comply with a subpoena. Zero-knowledge encryption sidesteps this entirely: the server (or in our case, no server at all) never sees the plaintext. The only parties who can read the message are those who possess the key.
AES-256-GCM: The Standard That Actually Holds
AES-GCM (Galois/Counter Mode) is the encryption algorithm used in TLS 1.3, Signal, WhatsApp, and the majority of well-engineered secure systems. AES stands for Advanced Encryption Standard β a block cipher standardized by NIST in 2001 after a rigorous five-year public competition. The 256 refers to key length in bits. With 256 bits, the keyspace is 2^256 possible keys β a number that makes brute force computationally impossible even if every atom in the observable universe were a processor running for the age of the universe. The "GCM" part adds authenticated encryption: it simultaneously encrypts the data and produces an authentication tag that verifies neither the ciphertext nor the associated data was tampered with. Crucially, if you try to decrypt with the wrong key, AES-GCM doesn't just give you garbled output β it throws an authentication error, which is why a bad passphrase is immediately detectable rather than silently producing corrupted plaintext.
This authentication property is what separates AES-GCM from older modes like AES-CBC, which were vulnerable to padding oracle attacks and malleability. With GCM, if an attacker flips a bit in the ciphertext, the authentication tag check fails on decryption. The integrity of the message is cryptographically guaranteed.
The Key Derivation Problem β And Why PBKDF2 Exists
A 256-bit AES key needs to come from somewhere. If a user types a passphrase, that passphrase is almost certainly shorter and less random than 256 bits of entropy. You cannot simply use the bytes of a passphrase as a key β the keyspace would be far too small and an attacker could enumerate common phrases rapidly. This is the key derivation problem, and PBKDF2 (Password-Based Key Derivation Function 2) is the answer to it.
PBKDF2 deliberately makes key derivation slow by running a hash function (SHA-256 here) a specified number of times β called iterations. This tool defaults to 250,000 iterations. This means anyone who wants to guess your passphrase must run SHA-256 a quarter million times per guess attempt. On modern hardware, this costs around 100ms per guess. An attacker who can make 10,000 guesses per second without PBKDF2 is now limited to roughly 10 guesses per second β a 1000x reduction in attack speed. Increasing iterations to 500,000 halves the attack rate again, at the cost of a slightly longer wait during legitimate encryption and decryption.
PBKDF2 also takes a salt as input β a random 128-bit value generated fresh for every encryption. The salt ensures that two notes encrypted with the same passphrase produce entirely different ciphertexts and require entirely separate brute-force efforts. Without a salt, an attacker who precomputes hashes for common passphrases (a "rainbow table") could crack many notes simultaneously. The salt makes precomputation worthless.
What "Zero Server" Actually Means for Your Privacy
Browser-side encryption using the Web Crypto API means the encryption and decryption happen entirely in the JavaScript engine of your browser. The passphrase never leaves your device. The plaintext never leaves your device. What gets shared is a base64-encoded blob β the ciphertext β which is mathematically indistinguishable from random noise without the key.
The shareable payload format used here packs: one version byte, 16 bytes of random salt, 12 bytes of random initialization vector (IV), and then the AES-GCM ciphertext. This is standard, self-contained, and requires nothing external to decrypt. The URL fragment (the part after the #) is another useful property: browsers never send URL fragments to servers in HTTP requests. If you embed the payload in a URL hash, the server hosting the decryption page never receives the encrypted data in its access logs. The payload lives only in the URL bar on the sender's and recipient's devices.
The Self-Destruct Mechanic β What It Protects Against and What It Doesn't
The self-destruct feature clears the decrypted note from the browser's DOM after 30 seconds. This protects against a specific threat: someone who physically walks up to a screen after a recipient has unlocked a note and leaves it visible. It also provides a mild deterrent against lazy screenshot-taking. It does not protect against a determined attacker who screenshots immediately, records the screen, or reads the page's DOM before the timer expires. The JavaScript has no ability to prevent those actions.
Similarly, "self-destruct" here operates in the browser only. The encrypted payload β the opaque blob β persists wherever it was shared: in an email, a chat log, a text message. The encryption itself remains intact on that blob indefinitely. What self-destructs is the decrypted content in the browser session, not the ciphertext. This is an important distinction. The security model is: the ciphertext can exist publicly forever, and it reveals nothing without the passphrase. The self-destruct is a UI-layer convenience, not a cryptographic guarantee.
Passphrase Hygiene: The Only Remaining Weak Link
The mathematics of AES-256-GCM is not the vulnerability. PBKDF2 with a quarter-million iterations is not the vulnerability. The IV and salt randomness from the Web Crypto API's getRandomValues() function β backed by the operating system's CSPRNG β is not the vulnerability. The only meaningful attack surface remaining is the passphrase itself. A passphrase of "password123" makes the entire construction worthless: it would be guessed in the first few milliseconds of any competent attack.
A genuinely strong passphrase for this use case has three properties: length (15+ characters), unpredictability (not a common phrase), and it is shared through a different channel than the ciphertext. If you email someone the encrypted payload and also email them the passphrase, you've created a single point of failure β email. A better flow: send the payload in an email, and the passphrase in a text message. Or use a prearranged shared passphrase the recipient already knows. The security of the entire system collapses to the security of the passphrase exchange channel.
This is the foundational insight behind all symmetric encryption systems: the cipher is a solved problem; key distribution is the hard part. This tool handles the cipher correctly. The key distribution is up to you.