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).

version 1 B sender pub 32 B ephemeral pub 32 B slots 48 B each nonce 24 B ciphertext + tag payload
Envelope layout (version 2)

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:

Read the protocol spec