Your private balance has its own keys. They come from one signature in your wallet, in your browser, and no server ever sees them.
Opening your keys
/private asks only when you click.
Set up keys. Your wallet signs one fixed typed-data request, shown on the page. The first time on a device it asks twice, to check the signature is stable.Restore from backup. An encrypted file plus its passphrase. No wallet is needed.
Your keys stay in memory in the tab. Lock this tab forgets them, as does a reload or a switch to another wallet, and the wallet asks again next time. The notes your browser has found are cached on the device, encrypted under a key from the same root, so the next scan only reads new logs.
Where the keys come from
The signature goes through a key derivation function into a 32-byte root, and every key comes from that root. The request has a domain and names no chain and no contract, so a wallet shows whose it is and the keys hold across networks. It never changes, because anything else would give new keys and an empty balance.
A signature of this request is your keys, for good. There is no way to rotate them short of moving your notes to a new balance, so sign it only on the ZKDepth app.
Most wallets sign the same request the same way every time. The client checks this and refuses a wallet that does not, because its keys could never be derived again.
What each key does
| Key | What it does |
|---|---|
Spending key sk | Proves you own a note. Whoever holds it can spend your notes |
Nullifier key nk | Derives the nullifier that marks your note as spent |
| Viewing key | Finds your notes and their amounts, and recognises the spent ones. It cannot spend |
| Fresh address keys | One-time addresses: withdrawals that should not link back to your wallet, and gas for a send with no relayer |
Your private address starts with zkd1. It is what others send to. Your viewing key starts with zkdview1, and the app shows it only on a click. Whoever holds it can read every note of this balance, so share it only with someone who should.
Finding your notes
Each note from a deposit, a transfer or a sealed batch carries a ciphertext encrypted to your viewing key. Your browser scans pool logs and tries to open each one, with a one-byte view tag to skip most of them. An action's output has no ciphertext: your keys recompute its blinding from the action's first nullifier. Your browser rebuilds the tree from the same logs, so a new device needs only your keys and the chain.
Backup
The backup is one encrypted file: the key root under a passphrase you choose (PBKDF2 with 600,000 rounds, then AES-GCM). Pick a strong passphrase: the file is only as hard to open as it is. The passphrase is never sent anywhere.
Losing your wallet with no backup loses the balance. Nobody can restore it, and that is what no admin path means.
Showing a note to someone
The disclose circuit proves up to 8 chosen notes belong to one spending key, with their amounts and, for spent ones, the nullifier each published. It reveals nothing else about the key or its other notes. It runs off chain, only you can start it, and the app downloads the proof as a file.
A prover can leave a spend out, so a disclosure shows ownership of these notes and never proves what someone holds now.
packages/zk/src/keys.tsthe key request and the derivationpackages/zk/src/vault.tsthe encrypted backupcircuits/src/disclose.circomselective disclosure