How OneTimeMessage.com Keeps Secrets: A Practical, Technical Deep-Dive into Our Encryption
When you share something through OneTimeMessage.com, you’re asking for two things at once: privacy (nobody else should read it) and control (it should disappear after a single view). Achieving both requires more than “some encryption.” It requires a design where keys aren’t stored, links are unguessable, and-when you want even more protection-the message is double-encrypted so the server never sees the cleartext at all.
This article explains, in plain language and with enough technical depth for security-minded readers, how our system works and why breaking it without the one-time URL-and, when used, the password-is computationally infeasible with today’s methods.
The Building Blocks (and Why We Chose Them)
- AES-256-GCM (AEAD)
Our standard cipher is AES with a 256-bit key in Galois/Counter Mode (GCM). GCM is an authenticated encryption scheme (AEAD): it gives you confidentiality (can’t read the message) and integrity (can’t undetectably change it). Decryption with the wrong key (or modified ciphertext) fails with an authentication error. - PBKDF2-HMAC-SHA-256 (Key Derivation)
When a password is part of the story, we never use it “as a key.” We run it through PBKDF2 with SHA-256, a unique per-message salt, and a large iteration count to slow down offline guessing. This means each password guess costs real CPU time, making brute-force attacks impractical for well-chosen passwords. - High-entropy one-time URLs
Your link includes a random 50-character slug of[a–z0–9]
. That’s 36 symbols per position. The total keyspace is 3650, which is roughly 2258. In other words, the URL itself is a secret with key-sized entropy. - Random Nonces / IVs
Every AES-GCM encryption uses a fresh 12-byte nonce (IV) generated by a cryptographically secure RNG. Never reused, never predictable.
These are industry-standard primitives, combined to minimize what the server has to know and to maximize the cost of any offline attack.
Standard Flow: Server-Side AES-256-GCM with a One-Time URL (and Optional Password)
1) Creation
- Your browser sends the plaintext message to our API (HTTPS).
- The server generates or uses the one-time URL key (the slug) and, if you supplied a password, runs it through PBKDF2-HMAC-SHA-256 with a unique salt.
- It constructs the final encryption key (derived from the URL key and, if present, the password KDF output).
- It encrypts the message with AES-256-GCM using a new 12-byte IV; stores only the ciphertext and minimal metadata needed to satisfy the one-time workflow.
No decryption key is stored. The server can reconstruct the key only when provided the full, correct URL key (and, if used, the exact password).
2) Viewing
- The recipient opens the one-time link. (Optionally, they also enter the password.)
- The server re-derives the same key material from the URL key (+ password KDF if used).
- It decrypts once, verifies the GCM authentication tag, and-if successful-returns the plaintext to the viewer exactly once, then deletes it.
If the password is wrong, GCM authentication fails and decryption is rejected. Nothing leaks.
Why the One-Time URL Makes Brute Force Useless
Our link slug is 50 characters drawn from 36 possibilities (a–z
, 0–9
). That means:
- Entropy: ~5.17 bits per character × 50 ≈ 258 bits of entropy.
- Search space: ~2258 possibilities.
Even with planet-scale compute, enumerating or guessing that slug is fantastically out of reach. This is why we treat the URL itself as a secret key-and why knowing the URL is a prerequisite to even attempting decryption.
Importantly, we also split and store only a fragment of that URL internally to locate blobs, so the stored filename doesn’t reveal enough information to reconstruct the full decryption key. The necessary secret remains the full URL you share.
Adding a Password: What Extra Protection It Provides
When you add a password, we apply PBKDF2-HMAC-SHA-256 with a per-message salt and a high iteration count. That makes every incorrect guess expensive for an attacker. Even if someone stole a ciphertext, they would have to perform the KDF per guess and still pass AES-GCM authentication. This turns password guessing into a slow, expensive exercise-and gains you another factor that isn’t present in the URL.
Practical guidance: Choose a password that’s long and unguessable (e.g., 12–16 characters or a multi-word passphrase). Our KDF setup makes weak passwords harder to brute force, but strong passwords make it functionally impossible.
“Detecting” AES-256-GCM Without Storing Secrets (What That Really Means)
You may see us say we can detect when content was encrypted with AES-GCM “without storing any information.” Here’s what that means in practice:
- Self-describing containers. We package ciphertext with a small, non-secret header that records the algorithm and parameters (e.g.,
gcm|12
for AES-GCM with a 12-byte IV). - Client-side pre-encryption tokens (explained later) are even more explicit:
otm-ue1|pbkdf2|sha256|200000|<salt>|gcm|12|<iv>|<ciphertext>
Seeing this header lets us recognize the format so we know how to attempt decryption (which KDF, IV length, etc.). It doesn’t reveal the key and doesn’t enable decryption without the correct URL key (and password, if used). AES-GCM’s authentication tag ensures that wrong keys or tampering cleanly fail.
So “detection” here is about format identification, not a cryptographic fingerprint that weakens security.
IP Lock: What It Is and How It Helps
IP lock is an optional setting you can apply when creating a one-time message. You provide an IP address, and we bind the message so it can only be decrypted from that address. At read time we verify the viewer’s IP before any decryption is attempted.
- Benefit: Even if someone steals the URL (and even the password), they still can’t open the message unless they do so from the allowed IP.
- Caveats: NATs, VPNs, and dynamic IPs can change what the receiver presents. Use IP lock only when you’re confident of the recipient’s address.
This is defense-in-depth-a network-level “fence” around an already encrypted, one-time secret.
What If an Attacker “Got the Server”?
Design for compromise means we assume the worst and still protect your content:
- Keys aren’t stored. The server can only reconstruct a decryption key from the full one-time URL key (which it doesn’t keep) and the optional password (which it never knows in plaintext).
- Stored names don’t reveal the key. We keep only a safe fragment of the URL to locate a file; it’s not enough to derive the key.
- AES-GCM authentication. Even if an attacker tampers with ciphertext or metadata, decryption will fail authentication checks.
- One-time semantics. Secrets are deleted at first successful view, shrinking the window for any offline attack.
- With pre-encryption (below), the server never sees the cleartext-ever. Even in a total compromise, the attacker still cannot recover the message without the user’s client-side password.
The One-Time URL Is a Key, Not Just an Address
Traditional links are identifiers. Our links are identifiers and keys. They’re random, high-entropy secrets that:
- Tell the server which encrypted blob to fetch.
- Provide the cryptographic material needed to derive the decryption key.
Unless an attacker knows that full slug, key derivation is impossible. And unless they also know your password (if you set one), PBKDF2 ensures decryption remains infeasible. This follows the same spirit as leading best practices in secure link-based secrets: the URL is treated as a bearer secret with sufficient entropy to act as a key.
Double Encryption (Pre-Encryption) and Why It’s Even Stronger
We recently introduced pre-encryption (“Ultra Encrypt”)-a purely client-side encryption workflow in your browser:
- Your browser encrypts the message with AES-GCM (256-bit) using a key derived from your password via PBKDF2-SHA-256, with a 16-byte salt, 200,000 iterations, and a 12-byte IV.
- The browser produces a self-describing token:
otm-ue1|pbkdf2|sha256|200000|<salt>|gcm|12|<iv>|<ciphertext>
- That ciphertext (not your plaintext) is sent to our server and stored.
- We encrypt it again using our standard server-side AES-256-GCM keyed by the one-time URL (and optional server-side password).
- At read time, the server decrypts once (using the URL key), returns the inner client-side ciphertext token to the browser, and the browser decrypts it with the user’s password.
Why this is so secure
- Zero-knowledge on the server. With pre-encryption enabled, the server never handles your cleartext. Even if the server and all storage were compromised, attackers would still face a properly KDF-hardened AES-GCM ciphertext with no password.
- Independent layers. Two distinct AES-GCM encryptions with different keys, different IVs, and different salts. There’s no structural shortcut: an attacker must defeat both layers (and the inner one is only decryptable with your password).
- Tamper resistance squared. Each layer has its own GCM authentication. Any modification breaks one (or both) tags and is rejected.
This is defense in depth done right. The outer layer enforces the one-time semantics and optional IP lock. The inner layer ensures only people who know your password can ever see the message content-even we can’t.
“How Do You Know It’s Pre-Encrypted If You Don’t Store Flags?”
We don’t store a flag. We recognize the token. The pre-encrypted payload is formatted to be self-describing:
otm-ue1 | pbkdf2 | sha256 | 200000 | <salt> | gcm | 12 | <iv> | <ciphertext>
otm-ue1
- format/version marker (not secret)pbkdf2|sha256|200000
- KDF recipe<salt>
- per-message salt (base64url)gcm|12
- AES-GCM with a 12-byte IV<iv>
- random 12-byte IV (base64url)<ciphertext>
- the data (base64url)
We can detect that the content is a client-side AES-GCM token and must be returned to the browser for decryption. But detection does not enable decryption-the password never leaves your device.
Putting It Together: Three Protection Levels
- One-Time URL only (no password)
Security rests on the unpredictability of the 50-char URL slug and AES-GCM integrity. Even this baseline is extraordinarily strong because the URL is a 258-bit secret. - URL + Password
Adds a second factor. The key is derived from both the link secret and your PBKDF2-hardened password. Offline guessing becomes prohibitively expensive. Wrong password = instant GCM auth failure. - Pre-Encryption (Client) + Standard (Server)
Your browser encrypts first (with your password), the server encrypts that ciphertext again (with the one-time-URL key). At read time, the server only ever returns the still-encrypted client token, and your browser decrypts it. Even with full server compromise, message confidentiality depends on a password the server never saw.
Add IP lock to any of the above to restrict where the one-time link can be opened from-useful when the recipient’s IP is known and stable.
Threat Model Highlights
- Passive network attackers: TLS protects the transport; AES-GCM protects the content. No plaintext leaks.
- URL leak / interception: If the link leaks, the attacker still needs the password (if set). With IP lock, they also need to be on the allowed address to even attempt decryption.
- Server compromise: No decryption keys are at rest; filenames don’t encode enough to derive them; pre-encryption means no plaintext exists server-side at all.
- Tampering: AES-GCM rejects modified content via authentication tag failure.
- Brute force: URL entropy (~2258) is far beyond feasible search. Passwords are PBKDF2-hardened with per-message salt and high iteration counts; choose strong passphrases to maximize protection.
What “Virtually Impossible” Really Means
Cryptography can’t promise literal impossibility, but it can push an attack so far beyond realistic cost and time that it is, for all practical purposes, impossible:
- Defeating AES-256-GCM directly is not viable with current public knowledge.
- Guessing a 50-char base-36 URL is astronomically out of reach.
- PBKDF2-hardened passwords multiply the cost of each guess.
- Two independent layers (client pre-encryption + server encryption) add multiplicative protection.
- One-time semantics and IP lock narrow windows of opportunity and exposure.
When used together, these measures mean your message is accessible only with the correct unique one-time URL and, when used, the correct password-and, optionally, from the correct IP.
A Note on Usability and Safety
- If you opt into pre-encryption, save and share the password via a secure channel. We cannot recover it or your plaintext.
- Prefer long passphrases (e.g., 3–5 random words) for excellent strength and memorability.
- IP lock is powerful, but use it when the recipient’s IP is known and stable.
In Summary
- Every one-time message is protected by AES-256-GCM and a high-entropy, unguessable URL that functions as a decryption key.
- Adding a password introduces PBKDF2-hardened key derivation, making offline guessing impractical.
- Our pre-encryption option double-encrypts your data-once in your browser, once on our server-so that we never see your plaintext, and attackers can’t decrypt it even if the server were compromised.
- An optional IP lock adds a network-layer gate: the right key, the right password, and the right place.
That’s how we make it virtually impossible for anyone but your intended recipient to read your message-by combining carefully chosen cryptography, one-time semantics, and a privacy-first architecture where secrets (and especially keys) are never left lying around.