How it works
No inventions - only well-studied primitives: BIP-39, X25519, HKDF-SHA256, XChaCha20-Poly1305. Here is the whole path, in plain language.
12 words are the whole identity
A profile starts from a BIP-39 mnemonic - 12 English words holding 128 bits of entropy. The words are stretched into a seed, and HKDF derives the encryption key pair from it. The same words on any device restore the same keys: there is no “account” to recover, only the phrase.
The address is the public key
Your X25519 public key, encoded in bech32 with the sk prefix, is your address - about 60 characters starting with sk1. Hand it over as text or a QR code. There is no directory to register in and no server that maps names to people.
sk1qsva3e52awafjvedj5ethvc5hs9j4t0ml26m83kn6kycsh9m46rejzha
A message becomes an envelope
The text is encrypted once with a random message key using XChaCha20-Poly1305. Then that key is wrapped into a slot for every recipient - and always into one more slot for you. That is why your own sent messages stay readable: decrypting your history is the same operation as reading incoming mail.
Slots are anonymous and shuffled: the envelope carries no addresses, so an outsider sees only sizes. Each slot key is agreed via two X25519 handshakes - one with an ephemeral key generated for this envelope (forward secrecy), one with the sender’s long-term key (sender authentication).
The envelope travels as plain text
The binary envelope is base64-wrapped into an armored block. It is self-contained: paste it into a messenger, an email, a forum post or a file - any channel that delivers text delivers Secret Keeper messages.
-----BEGIN SECRET MESSAGE V1----- AlXhZ0Qq7bfPj…base64…M42kLBi6p4Jro -----END SECRET MESSAGE V1-----
Files: the .skf container
Files use the same slot scheme, but the body is encrypted in chunks so that a multi-gigabyte video streams through without loading into memory. Chunk nonces follow the STREAM construction (as in age and Tink): a counter catches reordering and duplication, a final-byte catches truncation. Even the file name is inside the encrypted header.
Backups
A backup is a .skb file: settings, contacts and history in a single container encrypted to yourself - the same scheme as encrypted files, so nothing is readable from the outside, not even contact addresses. The seed phrase is never in the backup - the profile is restored from the 12 words, the backup restores everything around them.
What this buys
- Forward secrecy
- a fresh ephemeral key for every envelope
- Sender is readable
- your own slot in every envelope you send
- No state
- no pairwise sessions, nothing stored on servers
- No user IDs
- the address is the public key itself
- Two implementations
- Dart in the app, @noble in the extension - cross-checked by shared test vectors
Want to verify?
The full byte-level specification is public - same document the app and the extension are tested against: