So you find us again

The technology

Why we cannot read your message

Security here is not a promise – it is a property of the system: your message is encrypted in your browser before it ever reaches us, and the key never reaches us at all. This page explains exactly how that works – readable without prior knowledge, precise enough for people who want to verify it.

Encryption
AES-256-GCM
Key
256 bits, only in the link
Password hardening
PBKDF2-SHA256 · 600,000 rounds
Key derivation
HKDF-SHA256
Runs in
your browser (WebCrypto)
The link

One link, two worlds

The whole system rests on a single trick: the link consists of two parts that never travel the same way.

The access code

The part before the hash sign is a random 128-bit identifier (16 random bytes, hex encoded). It only tells our server which encrypted record to look up – it reveals nothing about the content. Guessing it is hopeless: even at a billion attempts per second, finding one would take longer, on average, than the universe has existed.

The key

Everything after the hash sign is called the URL fragment – and browsers never transmit this part of an address to any server. That has been standardised web behaviour for decades; it is not a feature we built. The key therefore appears in no request, no server log and no proxy. It exists only inside the link itself.

Ciphertext and key are physically separated: the ciphertext sits with us, the key only in the link. Whoever has just one of the two has nothing.

When you send

What happens when you click “Encrypt”

  1. Step 1

    Your browser rolls the key

    32 bytes – 256 bits – from your browser’s cryptographic random generator (WebCrypto, fed by your operating system’s entropy). Not from Math.random(), which would be predictable. 2²⁵⁶ possibilities is more than the estimated number of atoms in the visible universe.

  2. Step 2

    Encryption happens locally

    Your text is encrypted with AES-256-GCM – entirely inside your browser. If you set a password, it is first stretched through 600,000 PBKDF2 rounds and then folded into the key via HKDF, mathematically inseparably. The plaintext never leaves your device.

  3. Step 3

    Only the ciphertext is uploaded

    What reaches our server is an “envelope”: ciphertext, salt and IV – values that are worthless without the key. The key itself is attached to the link afterwards, in your browser: behind the hash sign, in the part browsers never transmit.

The building blocks

Four standard algorithms, nothing home-made

Good cryptography is never invented in-house – it is proven standards, composed correctly. These four do the work here:

AES-256-GCM

Encryption

AES has been the worldwide standard for symmetric encryption since 2001 – used by banks, governments and practically every HTTPS connection, never practically broken in more than twenty years of public analysis. “256” is the key length in bits, the strongest variant. GCM is the mode of operation and does two things at once: it encrypts, and it computes a 16-byte authenticity seal (the authentication tag) over the ciphertext. On decryption that seal is checked first: if even a single bit is off – wrong key, wrong password, tampered data – decryption fails cleanly instead of producing garbage that looks like a message.

ct = AES-256-GCM(key, iv, plaintext)

PBKDF2-SHA256

Password hardening

People pick weak passwords – PBKDF2 turns them into usable key material anyway, through deliberate slowness: the password is run through HMAC-SHA256 600,000 times in a row (the value recommended by OWASP). For the recipient that is a one-off fraction of a second; for an attacker, every single guess costs 600,000 computations. A random salt per message makes precomputed tables useless, and the round count is stored in the envelope – so we can raise it in the future without breaking old messages.

pk = PBKDF2-SHA256(password, salt, 600,000)

HKDF-SHA256

Key derivation

HKDF blends the link key and the stretched password into the actual AES key. That is more than gluing them together: the final key emerges mathematically from both ingredients at once – there is no “decrypt halfway and guess the rest”. A fixed context string (“easysafeshare:v1:aes-gcm”) additionally guarantees that the same bytes would never yield the same key in any other context – domain separation, exactly as the textbook demands.

key = HKDF-SHA256(fk ‖ pk, salt, info)

CSPRNG

Randomness

Every key, salt and IV comes from crypto.getRandomValues() – the cryptographically secure random generator your browser feeds from operating-system entropy. It is the same randomness your browser uses to secure TLS connections. Predictable randomness is the classic backdoor of badly built crypto – here it is ruled out by construction, and WebCrypto is only available on HTTPS pages in the first place.

fk = 32 random bytes, salt = 16, iv = 12
The construction

The complete formula

This is how your browser composes the building blocks – line by line, exactly what our published code does:

fk = 32 random bytes into the link after #, never transmitted
salt = 16 random bytes stored openly in the envelope – not a secret
pk = PBKDF2-SHA256(password, salt, 600,000) only when a password is set
key = HKDF-SHA256(fk ‖ pk, salt, info) both factors, inseparably combined
ct = AES-256-GCM(key, iv, plaintext) iv = 12 random bytes per message

And this is everything our database holds:

{
  "v": 1,
  "alg": "AES-GCM",
  "salt": "Jm3qJdgQ…",
  "iv": "p0XwR2Ka…",
  "ct": "T9zKfLm2wQvXr8…",
  "kdf": "PBKDF2-SHA256",
  "iter": 600000
}

Salt and IV are not secrets – they only ensure that identical messages never produce identical ciphertext. The one thing that can open this record is the key from the link. It was never here. Stealing our entire database – statistically the most common way data actually leaks – therefore yields nothing but unreadable blocks.

When it is opened

What happens when the recipient opens the link

  1. Step 1

    The page loads – and reveals nothing

    Loading the page only discloses that the message exists and whether it needs a password. The ciphertext is not handed out yet. That is why no link preview in a messenger, no crawler and no virus scanner can accidentally “use up” the message.

  2. Step 2

    One click, one delivery

    Only the click on “Open” fetches the envelope. For self-destructing messages the database deletes the record in the very same operation that hands it out – atomically. If two people open the link in the same millisecond, exactly one of them gets it; the database guarantees that, not our application code.

  3. Step 3

    Decryption is local again

    The recipient’s browser reads the key from the fragment, runs the same construction in reverse and verifies the GCM seal along the way. A mistyped password produces a clean error – and does not cost the message: the envelope stays in the browser’s memory, and the next attempt runs locally, with no round trip to the server. After decryption the key is wiped from the address bar.

The acid test

What an attacker actually gets

The most honest way to describe a security system: walk through what someone ends up with, given what they can steal.

  • Our entire database

    Only ciphertexts, salts and IVs. The key to every single message lives in its link – it was never on our server, so it is not in any copy of our server either.

    Nothing readable
  • The link – but a password is set

    The AES key only comes into existence from the link key and the password together. Without the password, all that remains is brute force – where every single candidate costs 600,000 PBKDF2 rounds.

    Nothing readable
  • Only the password

    Without the link, 256 bits of true randomness are missing. There is nothing to apply the password to – not even the ciphertext, because the access code is missing as well.

    Nothing readable
  • Link and password together

    Whoever holds both is, as far as the mathematics is concerned, the legitimate recipient. That is exactly why link and password belong in separate channels – the link by e-mail, the password by phone. An attacker would then have to compromise both channels at once.

    Readable

For self-destructing messages there is one more property: an intercepted and read link is noticed, because the message is visibly gone afterwards. Silent eavesdropping is impossible.

Honesty

What even this technology cannot do

A security promise is only worth as much as the clarity about its limits. These three apply to every browser-based encryption – including ours.

  • The recipient’s device

    Whoever is allowed to open the message can photograph or copy it – no software on earth stops a camera pointed at a screen. A browser extension with full access to page content could read the plaintext, too. Encryption protects the journey, not the destination.

  • A compromised server

    If someone took over our server, they could serve tampered JavaScript that steals keys. That is the fundamental ceiling of all browser cryptography. Our answer is a strict Content Security Policy: the browser executes only our own script, signed per request – injected foreign code is blocked.

  • The complete link plus the password

    Whoever gets to the link and the password before the recipient can open the message. Mathematics cannot tell possession from theft – separating the channels is your job as the sender. We make it as easy for you as we can.

See for yourself

Everything on this page can be verified: open your browser’s developer tools, encrypt a test message and check for yourself what your browser sends to us – and what it does not.

Encrypt a message now