🔒

Private Preview

QEV Web Vault is currently in private preview. To request access, email the address below. You'll receive an access code within one business day.

Request access
bryanleonard@imagineqira.com
That code didn't match. Check for stray spaces.

Already tried it and want the native app instead? Download QEV for Mac or Windows.
Don't need a vault at all? Back to BRY-NFET-SX.

Browser-only encrypted envelope

A one-off secret,
sent without a server.

Type a message, type a secret phrase, get an encrypted vault file. Send the file through one channel and the phrase through another. No account. No server. Plaintext never leaves this tab — open DevTools and watch: after this page loads, there are zero network requests. XChaCha20-Poly1305 + Argon2id, running in your browser via libsodium.

Loading crypto module...
Who this is for
If any of these are you, this is built for you
Not everyone needs browser-only secret sharing. These are the specific cases where everything else is worse.

You need to send one secret, once

A credential during offboarding. A recovery phrase to a new employee. A document access token to a contractor for a single job. You do not want to create an account anywhere, invite anyone to a platform, or leave a copy sitting on a vendor's server. You want to hand over one thing and be done.

You want to verify nothing leaks

Signal requires trusting Signal. Email with a passphrase leaks metadata. Cloud password managers put ciphertext on someone else's hardware. Here you can open DevTools, perform an encrypt, perform a decrypt, and see zero network requests. The Content-Security-Policy on this page is connect-src 'none' — the browser itself refuses to let the page call anywhere.

You share the receiving end with someone non-technical

They need to open the box on their phone, on a laptop they borrowed, on a machine with no software installed. This page runs in any modern browser. Drop the file, type the phrase, read the message. No install. No signup. No QR scan with a second device.

You want to verify the page itself wasn't tampered with

The JavaScript is SRI-locked inside the HTML. The HTML is SHA-256 signed by the BRY-NFET-SX site integrity workflow. Compare the hashes on /verify against what your browser loaded. If they match, the page you just ran is the published, signed version.

Encrypt
Encrypt a note for yourself
Type a message and a password. Save the vault file. Remember the password. You can decrypt it later on any device.
1
The text you want to lock up. Anything you type. Up to 256 KiB. The text only exists in this browser tab. It is never sent to a server.
2
This phrase is the only thing that opens the box. It is never sent anywhere — it stays in your head. You need the exact same phrase to open the box later.

Pick a phrase, not a word. A 6-character password is crackable in hours on a single GPU. Four random words (like river-purple-dragon-cloud) would take trillions of years at the same cost. The generator below picks 4 random words for you.

If you forget the phrase, the box CANNOT be opened. There is no reset, no recovery, no backdoor.
(empty)
3
How hard the box is to break open. Stronger locks take longer to lock and unlock but are harder for a thief to break. The math is called Argon2id. The numbers it uses are stored inside the box so you don't need to remember them.
4
"Just for me" means you are saving a private note. "Share with someone" means you will send the box to a friend and tell them the secret phrase a different way (call them, text them). The math is the same; the label tells future-you what kind of box this was.
5
A random 24-byte number we pick for every box. It makes every lock unique even if you use the same secret phrase twice. You don't need to remember it — it's stored inside the box. Crypto people call this a "nonce" (number used once).
(generating...)
6
Another random number that mixes with your secret phrase to make the lock harder to pick. Different from the secret number above. Also stored inside the box. Crypto people call this a "salt".
(generating...)
7
The kind of math we use to lock the box. We use XChaCha20-Poly1305 (encryption) and Argon2id (password mixing). These are the same math used by Signal and other security tools. We don't change them.
XChaCha20-Poly1305 + Argon2id (cannot be changed)
8
The version of the locked box format. Version 2 is what we make today — it uses a random data key that is itself locked by your phrase. Older Version 1 boxes still open on this page. If we ever change the format again, future versions will get a new number.
BRY-NFET-SX VAULT V2 (made by version 0.28.1)

Locked! Save the box file and remember your secret phrase.

To open this box later you need two things: the box file (download below) and the secret phrase you typed (only in your head).

Box name (envelope ID): (computing...)

        
Important: If you are sharing this box with someone, send the box file and the secret phrase through different channels. Email the file, text the password. Never send both in the same place.

Decrypt
Open a vault
Drop or paste a vault file, type the password, get the message back.
Drop the .vault.json file or the vault-recovery-...txt recovery sheet here
Step 2 — the password. Type it in the field below. Do not paste it from the same place as the vault. Do not paste it from a chat window where the vault was sent.

Decrypted message


        
Honest Threat Model
What this protects, and what it does not
Every security tool needs honest framing. Here is the one for this one.

What this does protect

  • Confidentiality of your message against anyone without the secret phrase
  • Integrity of every byte of the vault — flipping any bit breaks decryption with a clear error
  • Every byte of metadata (salt, both nonces, KDF parameters, schema, version, mode, created_at, both AEAD algorithms) is bound into the authentication tag
  • A random data key encrypts your message; the secret phrase only unwraps that data key. The phrase is never the sole root of secrecy
  • The JavaScript on this page is integrity-protected via Subresource Integrity — the browser refuses to execute a modified version
  • Plaintext exists only in this browser tab. Zero network requests after page load. Verify in DevTools.

What this does not protect

  • Against anyone who has the secret phrase — protect it like you would a house key
  • Against weak phrases — Argon2id raises the cost but does not make a one-word phrase strong. Use 4+ random words or the generator
  • Against a compromised host server that ships malicious JavaScript at serve time — mitigated but not eliminated by SRI and the integrity-signed page. This is the real weakest link; if it matters, verify the signed integrity record on /verify
  • Against endpoint compromise — keyloggers, malware, screen recorders, shoulder-surfers
  • Against forgetting the phrase — if you lose it, the vault is permanently unrecoverable. There is no backdoor, no reset, no recovery. There is also no recovery keyslot (today)
  • This is not end-to-end messaging like Signal — there is no key exchange, no forward secrecy, no identity verification. It is a vault you share the phrase to
How It Works
Standard primitives. Standard library. No magic.
If you know cryptography, you can read the source. If you don't, here is the short version.
KDF

Argon2id

Your phrase is stretched by Argon2id. Strong lock (the default) uses opslimit 4 and memlimit 96 MiB — about 4 seconds per guess on modern hardware, so offline brute-force is expensive. The 16-byte salt is generated fresh per vault and stored alongside the ciphertext. Quick lock and Vault lock presets are also available.

AEAD

XChaCha20-Poly1305

A fresh random 32-byte vault key encrypts the message with XChaCha20-Poly1305 (24-byte content nonce, 16-byte Poly1305 tag). The vault key is then wrapped a second time with XChaCha20-Poly1305 under the Argon2id output (24-byte wrap nonce, 16-byte tag). Tampering with any byte of either ciphertext, either nonce, the salt, or the metadata breaks at least one of the two authentication tags on decrypt.

Library

libsodium.js

All cryptographic operations are delegated to libsodium.js, the same audited library used by Signal and many other security products. The page loads it once, runs a self-test, and refuses to enable encryption if the self-test fails.

Verify This Page
Don't trust us. Check the page yourself.
The integrity story is layered: the JavaScript is bound to the HTML by Subresource Integrity, the HTML is signed by the BRY-NFET-SX site integrity workflow.

Three things to check

  1. SRI. View the source of this page and look at the integrity attribute on the two <script> tags. The browser refuses to execute either script if the loaded bytes don't match the SHA-384 hash. If the page rendered and the form is enabled, SRI passed.
  2. Site integrity. Visit /verify and download the integrity record. vault/index.html, vault/chat.js, and vault/sodium.js are listed there with their SHA-256 hashes.
  3. Network silence. Open DevTools, switch to the Network tab, perform an encrypt and a decrypt. Confirm zero network requests after the initial page load. The Content-Security-Policy on this page sets connect-src 'none' — the browser blocks any attempt to call out.

One phrase. One vault. No accounts. No servers.

Encryption that fits on one page. Verifiable. Deletable. Yours.