Visualizer · runs in your browser

See the mechanics, not the marketing.

Four interactive walkthroughs of what the envelope actually does — then a token-gated panel that reads your own deployed store. The explainers use fixed sample data and run entirely client-side; the live panel calls the same-origin store and only ever reads non-secret data.

Explainer · encrypt / decrypt

Seal a secret through three tiers

A value is sealed under the tenant's DEK with a data-AAD, then the DEK is wrapped under the environment's KEK. Step through it — the console shows the exact call and encryption context.

KEK · kek_kv 1DEK · tenant acme · dek_ver 1sk_live_51H8xQ…plaintext · in memory
step 0 / 3plaintext held in memory — nothing sealed yet.

The data-AAD { tenant, column, dek_ver } and the wrap-AAD { tenant, "dek-wrap", kek_kv } are derived from the row, never passed by hand.

Explainer · placement integrity

Relocate a ciphertext, watch the tag fail

Copy one tenant's sealed blob into another tenant's row. On read, the store rebuilds the data-AAD from the destination row — a different tenant — so the GCM tag no longer verifies.

tenant = acme
tenant = globex
empty row
9f4c a1e0 ‖ tagsealed: { acme, STRIPE_KEY, 1 }
readyTenant acme holds one sealed secret.

This is placement integrity, not access control: an over-scoped token could still read globex legitimately. Isolation between tenants rests on token scoping.

Explainer · freshness anchor

Reject a rolled-back ciphertext on read

The authoritative { version, ciphertext_hash } lives in a Durable Object outside D1. A D1-write attacker can forge the version, but not the anchored hash — so a reverted blob fails the read check.

D1 · secrets rowattacker-writable
version
3
ciphertext
e83a 5510 c6fa 0d9e
sha256(ct)
…c6fa
Freshness DOoutside D1
version
3
ciphertext_hash
…c6fa
audit head
seq 41
200 OKRow hash matches the anchor — the current value verifies.

The anchor commits to a hash of the current ciphertext, not a version the attacker also controls. A fully-compromised account that writes both D1 and the DO still defeats it — the assumed-control boundary — with the immutable audit mirror as the backstop.

Explainer · crypto-shred

Drop one key, and honest erasure

Deleting a tenant's wrapped DEK makes all of its ciphertext undecryptable via the normal path at once — no row sweep. But real erasure completes later, and the store reports that true time, never "O(1), done."

tenant_deksdek_ver 1 · wrapped · status activeheld
  • STRIPE_KEYreadable
  • OAUTH_REFRESHreadable
  • WEBHOOK_SIGNINGreadable
readyThe tenant's DEK is held; its three secrets are readable.

Crypto-shred is the GDPR-erase primitive. It is irreversible only after those windows close — keep it behind an explicit soft-delete grace window.

Live store · token-gated

Point it at your own store

This runs against the store on this origin. It lists secret names and versions and reads the audit log with its hash-chain status — never a secret value. Your token is held in memory for this tab only and is never stored or logged.

Blank = this origin, so no CORS. Or e.g. https://secrets.example.com
Needs secrets:list to list, audit:read to read audit.

The site calls only GET /v1/secrets/… (names) and GET /v1/audit/…. It never requests plaintext.

Results appear here.

Fill the form and choose List secrets or Load audit.

Want the exact byte layout, golden vectors, and the error taxonomy?