10 min read
Why Your Keys Never Leave the Device
In CardanoWall, signing, sealing, and decryption all happen locally — the gateway publishes proofs and stores ciphertext but is designed never to receive your private keys.

In CardanoWall, your private keys stay on your device. The software that signs, seals, trial-decrypts, and verifies runs locally; the hosted gateway is designed never to receive your Identity Seed, your signing key, your recipient keys, or the material that decrypts a sealed file.
The gateway has plenty to do without those secrets. It can quote a price, accept already-encrypted ciphertext for storage, submit a Cardano transaction, index records, and track your balance. None of that requires the keys that prove authorship or open a sealed payload. The split is deliberate: the service helps move the proof, and you keep the secrets.
What keys are we talking about?
A Label 309 identity starts from a single value: a 32-byte Identity Seed. From that seed, any conforming software derives the keys an identity actually uses, in three roles:
- an Ed25519 key that signs records;
- an X25519 key that receives classically sealed records;
- a hybrid post-quantum key that receives post-quantum sealed records.
The derivation is deterministic. The same 32 bytes always produce the same three keypairs, in any conforming client. That is what makes the seed portable — and what makes it the one thing worth guarding. Anyone holding the seed can restore the identity, sign as it, and decrypt sealed records addressed to it. So the seed stays private, and everything below follows from that.
What does the client do locally?
The client handles every operation that touches a private key:
- generating or importing an Identity Seed;
- deriving the signing and receive keys from it;
- signing records;
- encrypting files before upload;
- building the sealed recipient slots that wrap a content key;
- trial-decrypting incoming records to find the ones addressed to you;
- decrypting ciphertext and recomputing the plaintext hash;
- verifying signatures and record structure.
The web app, the desktop app, the command-line tool, and any software built on the SDKs differ in how they store keys and how they unlock them. The principle does not change between them: private key material is not sent to the gateway.
What does the gateway do, then?
The gateway runs the publishing pipeline. It can:
- calculate a quote;
- receive already-encrypted ciphertext and return a content-addressed URI;
- accept a prepared proof record;
- submit a Cardano transaction and wait for confirmation;
- handle chain reorganizations and refund automatically if a publish permanently fails;
- index records into a shared feed;
- track your account balance;
- expose its API and emit lifecycle events.
These are real jobs, and they are most of the operational work. But not one of them needs a key that decrypts your sealed content. The gateway is a transport and operations layer. It is not your identity vault, and it is not designed to act like one.
Why does this separation matter?
Because a proof should stay verifiable without trusting the service that helped create it.
If a hosted service held the only copy of your keys, that service would become your root of trust. If it shut down, changed its terms, suffered a breach, or locked your account, your ability to sign, decrypt, or even verify could ride on it. That is the position Label 309 is built to avoid.
A Label 309 record is verifiable from public data. A verifier needs only the transaction metadata, optionally the content bytes, and a public Cardano explorer — no issuer server at any step. A sealed record can be opened by the key holder. A signed record can be checked against its signing key. The gateway can make publishing far easier, but by design it cannot read a properly sealed payload just because it helped put it on-chain.
That is the difference between a service that tells you it has a proof and a proof that stands on its own.
Can the gateway read my sealed files?
If the client sealed the content correctly, no — the gateway only ever sees ciphertext.
Here is how a sealed record is laid out. The public on-chain record commits to the plaintext hash — that hash, plus the block time, is the proof of timing. The encrypted payload itself never goes on-chain; it lives at a content-addressed URI (such as ar://). The content key is wrapped to one or more recipient public keys, one slot per recipient. The recipient (or the sender) fetches the ciphertext, decrypts it locally, and recomputes the plaintext hash to confirm it matches the on-chain commitment.
The gateway can see that a sealed record exists, and it can observe ciphertext size, upload timing, account activity, transaction status, and the public metadata. It is not designed to see the plaintext, and without the right private key the ciphertext stays unreadable. Two honest caveats sit alongside that: sealing protects confidentiality, not anonymity — observable metadata is still metadata — and a recipient who decrypts a file can always choose to leak the plaintext afterward. Encryption protects the bytes in transit and at rest, not what an authorized reader does next.
Can the gateway fake a valid proof?
It is designed so it cannot make an invalid proof pass independent verification.
A verifier checks the on-chain record, the record structure, the hashes, the signatures, and — for a sealed record it can open — the recomputed plaintext hash. If a gateway lied about a transaction, altered the record bytes, dropped a signature, or pointed at bytes that do not match the committed hash, an independent verifier should catch it.
That is a precise promise, and it is worth not over-stating. A gateway can still misbehave in ordinary operational ways: it can fail to publish, delay a transaction, return an error, misreport its own status, have an outage, or give you a poor experience. What it should not be able to do is turn an invalid proof into one that verifies cleanly against public data. Convenience can fail; the cryptographic claim does not depend on the gateway being honest.
What about the web app specifically?
The web app is software running in a browser, and that shapes its trust model.
The relevant boundary includes the browser, the application code that loads, any installed extensions, the device itself, and the unlock flow. A browser is convenient, but it is not the same environment as a desktop vault or a command-line tool running from a build you control. A malicious script in an unlocked session can read in-memory secrets; a strict content-security policy, minimal scripts, and an explicit unlock step reduce that exposure, but no web app can claim to eliminate it.
That is one reason a dedicated desktop client exists, for people who want local storage and tighter control over how keys are held. The invariant holds across every client — the gateway does not need your private keys — even though each client protects those keys differently. For a fuller account of where the line sits, see what CardanoWall can and cannot see.
What about the desktop app?
CardanoWall Desktop is an open-source, cross-platform application built around a local encrypted vault from the start.
A Rust core owns the identity vault, the cryptography, the sync engine, trial-decryption, and verification, with a webview that only renders the interface. Seeds and derived private keys are not handed to the webview as ordinary JavaScript strings; when content has to be previewed, decrypted bytes are streamed to the view through a dedicated channel rather than passing through the page as a string. Secrets are not sent to the gateway, and they do not cross into the renderer.
That architecture narrows the attack surface; it does not erase it. A compromised operating system, a malicious dependency, a keylogger, or user-approved malware can still defeat local security — the same honest limit any desktop wallet carries. Keeping keys out of the gateway and out of the renderer is a meaningful improvement, not a guarantee against a fully compromised host. For how it works in detail, see the overview of CardanoWall Desktop and offline proofs.
What about the command-line tool and the SDKs?
They matter because they make the same model available without the website.
A developer can keep a seed locally, sign records locally, seal files locally, and submit through any gateway. A continuous-integration system can publish with scoped API credentials while keeping identity material under the team's own controls. A company can build its own client or fold Label 309 into existing software. The division stays the same no matter which interface you reach for: the gateway publishes, the client holds the secrets.
The command-line tool and the SDKs are open source and gateway-agnostic, so the boundary is one you can inspect rather than one you have to take on trust.
What should never be sent to a gateway?
Never send these to a gateway — or to any website:
- your
L309-SEED-1…Identity Seed; - the raw seed in hex;
- a signing private key;
- an X25519 receive private key;
- a hybrid post-quantum receive secret;
- a passphrase that decrypts sealed content;
- plaintext you meant to keep private.
The gateway may legitimately need public keys, public signatures, the public record bytes, ciphertext, quote identifiers, API tokens, and account identifiers. Those are not private identity material. The rule is simple: if a workflow asks you to paste a secret somewhere, stop and ask why.
What still needs your care?
Local keys are only as safe as the environment around them. Cryptography keeps a gateway out of your secrets; it cannot protect a seed that a user copies into an attacker-controlled form. So you still need to:
- protect your Identity Seed and keep a real backup of it;
- verify a recipient's receive address before sealing anything sensitive;
- avoid phishing sites;
- be deliberate about browser extensions;
- keep your devices updated;
- use disk encryption where it fits;
- understand how decrypted files are cached;
- run trusted builds of the desktop and command-line tools;
- set key-management policies for shared or team workflows.
It is worth being blunt about the failure modes, because they are not symmetric. Lose the seed and your unlock factors, and future use of that identity is gone — though any proofs you already published still verify, forever, from public data. A stolen seed is a full identity compromise: the response is to create a new identity and deactivate the old one, not to reset a password. There is no reset; that is the cost of there being no custodian.
Why this matters for an open standard
An open proof standard should not depend on one trusted operator.
If CardanoWall vanished tomorrow, a Label 309 record should still be meaningful. If a company runs its own gateway, its records should still be standard. If you export your seed to another conforming client, it should derive the very same keys. That only works if the boundary stays clean: records are standard, verification is independent, gateways are replaceable, clients hold the secrets, and you can always back up the identity root yourself.
So "keys never leave the device" is not a slogan. It is part of what makes a Proof of Existence portable — a proof you can carry past any single service, including this one.
The short version
The gateway helps publish the proof. The client holds the secrets.
Private keys are not sent to the gateway. Content is encrypted before upload. Decryption happens locally. Verification does not depend on trusting a service's word. That is the security shape CardanoWall is built on — and the shape Label 309 is designed to keep open.
Further reading
- Your identity is a seed — what the Identity Seed is and why it is the real backup.
- How CardanoWall stores your identity — the encrypted vault and what the server can and cannot decrypt.
- What a proof does not prove — the honest limits of timing-and-integrity proofs.
- The Label 309 standard at label309.org, submitted to the Cardano CIP process and under review by the CIP editors.
- The open-source clients, SDKs, and gateway at github.com/cardanowall.