How Sigil works
Sigil splits one private key into three Shamir shares. Any two of them rebuild the key; one alone is useless. The shares live in three different trust domains:
| Share | Where it lives | Who controls it |
|---|---|---|
| Device | the user’s browser (localStorage, namespaced by wallet) | end user |
| Provider | Sigil backend, envelope-encrypted with Cloud KMS | Sigil |
| Recovery | your backend (default) or Sigil with a separate KEK | you (or Sigil) |
The reconstruction (Device + Provider) only happens inside the wallet iframe, in browser memory, for the milliseconds it takes to sign one message. Then the buffer is wiped.
The pieces
┌────────────────────────────────────────────────────────────────────┐│ Your app ││ ││ <SigilProvider/> ││ │ ││ ▼ postMessage ││ ┌──────────────────────┐ HTTPS ┌──────────────────────┐ ││ │ wallet iframe │────────────▶│ Sigil API │ ││ │ wallet.sigilkeys.com │ │ api.sigilkeys.com │ ││ │ │ │ │ ││ │ • generates key │ │ • lazy user records │ ││ │ • SSS split │ │ • provider share │ ││ │ • signs in memory │ │ under Cloud KMS │ ││ └──────────────────────┘ └──────────┬───────────┘ ││ │ ││ ┌─────────────────────────┘ ││ ▼ ││ ┌────────────────────────┐ ││ │ Your backend │ (recovery share custody) ││ │ POST /sigil/recovery │ ││ └────────────────────────┘ │└────────────────────────────────────────────────────────────────────┘What touches what
- Your bundle ships only the SDK + a publishable key. No secrets.
- The iframe loads from
wallet.sigilkeys.com, so the browser enforces origin isolation. The iframe code is the only place the reconstructed private key ever exists. - Sigil API stores only the encrypted provider share and the metadata needed to authenticate the end user (or proxy your OIDC).
- Cloud KMS holds the KEK that wraps the DEK that wraps the share.
AAD binds it to
(organization_id, wallet_id)so a leaked ciphertext can’t be replayed for another wallet. - Your backend (in the default recovery model) receives a webhook with the recovery share at wallet creation and serves it back during recovery. See Recovery for details.
Why an iframe
Browsers enforce a real, hardware-backed isolation between origins.
Embedding Sigil as a same-origin SDK would mean any XSS in your app could
read the reconstructed key. By living on a separate origin
(wallet.sigilkeys.com), the iframe is unreachable from your DOM —
your code can only talk to it via postMessage, and Sigil verifies every
message against the per-org allowlist of origins.
The iframe ships a strict Content-Security-Policy, no third-party
scripts, no analytics, no inline JS. Reproducible builds.