Myne
Protocol specification v0.1 · draft

The protocol, in the open.

Myne's at-rest encryption is public by design — KDF parameters, AEAD construction, the key hierarchy, recovery derivation, and account-number scheme, all detailed enough to review without reading the source. Marketing copy may never exceed what this spec guarantees.

myne-protocol-v0.1 RFC 2119 conventions Cross-impl test vectors
§2 · Cryptographic primitives

Boring, well-vetted, no custom crypto.

Every primitive is a published RFC implemented by an audited library — RustCrypto on desktop, libsodium-equivalent elsewhere. No client ships a hand-rolled primitive; cross-implementation byte-compatibility is pinned by a public test-vector repo.

KDF · password → wrap key
Argon2id
m = 256 MiB · t = 3 · p = 2

RFC 9106. ~1 s on a 2024 laptop. Parameters live in vault.meta, bound into the AEAD AAD against downgrade.

AEAD · note encryption
XChaCha20-Poly1305
256-bit key · 192-bit nonce · + CTX

RFC 8439 extended-nonce, wrapped in the CTX commitment construction to close partitioning-oracle attacks on weak passwords.

Recovery phrase
BIP-39 · 24 words
256-bit entropy

Used only as an encoding. The phrase feeds Argon2id directly — not BIP-39's weak 2048-iteration PBKDF2 seed.

Hashing · subkeys · RNG
SHA-256 · HKDF
OS CSPRNG

HKDF-SHA-256 derives every subkey through one canonical helper with registered context strings. All randomness from the OS CSPRNG.

§3 · Key hierarchy

A random root key, wrapped two ways.

The root key is 32 random bytes — never derived from the password. Two independent credentials each wrap their own copy, so either opens the vault, and a password change re-wraps one 64-byte field instead of re-encrypting every note.

Credential A
Master password
Argon2id → password_wrap_key
Credential B
24-word recovery phrase
Argon2id → recovery_wrap_key
↓   each wraps a copy of   ↓
Root key
32 random bytes · client RAM only
itemsKey_wrap derived from root key — never stored
itemsKey one per vault — persists across password changes
item_key one per note — encrypts the note plaintext
note.myn encrypted markdown — title, folders, tags, links all inside the blob
§6 · §9 · Per-note encryption

What lands on disk is noise.

Each note is a flat <uuid>.myn file. Folders are virtual — the hierarchy is a path string inside the encrypted frontmatter, so a filesystem observer sees only opaque blobs. The on-disk layout:

Bytes
Field
MY01
magic — per-note blob
1 B
protocol version 0x01
1 B
reserved (0x00)
16 B
items_key_id — which itemsKey wrapped this note
24 B
item_key_nonce
2 B
enc_item_key_len (= 64, big-endian)
64 B
enc_item_key — item_key + CTX commitment tag
24 B
content_nonce
4 B
ciphertext_len (big-endian)
M B
ciphertext — encrypted markdown + CTX commitment tag

A successful decrypt commits the encryptor to the protocol version, the itemsKey identity, the note UUID, and the content type — substitution, downgrade, and key-confusion all fail the single constant-time CTX tag check.

§8 · Account number

An identifier, not a key.

A Mullvad-style self-generated number replaces email at signup. Possessing it grants no read access — only the password or recovery phrase derive the root key. Its hash is mixed into the Argon2id salts to prevent cross-account precomputation.

MY-XXXX-XXXX-XXXX-XXXX-XXXX
95
bits entropy
Crockford
base32 · no I L O U
Damm-32
1 check char

Bearer-token semantics: treat it like cash. The Damm-32 check catches every single-character substitution and every adjacent transposition.

§7 · Recovery

Two ways in. No third.

The recovery phrase survives password changes — its wrapped root-key copy and salt are preserved when you set a new password. It is never sent to any server. v0.1 is hard zero-knowledge.

The one irreversible consequence

Lose both the password and the phrase and the vault is permanently unrecoverable. There is no forgot-password email, no admin reset, no backdoor — the deliberate cost of zero-knowledge.

Threat model v0.1

What we defend — and what we don't.

Every adversary is rated against one of four honest levels. The not-protected list is published in the same document, in plain language.

Strong guarantee Mitigated Best-effort Out of scope
A1
Passive cloud provider
Server stores only opaque ciphertext. Keys and plaintext never leave the client.
Strong
A2
Compelled lawful access
The server cannot disclose what it does not possess — no plaintext, titles, or structure.
Strong
A3
Passive network attacker
TLS in transit plus client-side E2EE before transit — encrypted bytes between encrypted bytes.
Strong
A5
Lost / stolen device (locked)
Root key derived via Argon2id from a password the device never stores.
Strong
A11
Insider threat (the Myne team)
The team gets no more access than any external attacker. Keys never leave the client.
Strong
A4
Active network attacker (MitM)
Strict TLS + certificate pinning. A MitM still cannot decrypt notes.
Mitigated
A6
Lost / stolen device (unlocked)
Auto-lock on idle zeroizes keys and tears down the open note — narrows the window, not closes it.
Mitigated
A9
Compromised build / distribution
Reproducible builds, code-signed releases, verified auto-update.
Mitigated
A7
Malware on your device
Active malware defeats any user-mode encryption. Screen-capture exclusion is defense-in-depth.
Best-effort
A8
Compromised dependency / supply chain
Hash-pinned lockfiles, a minimal dependency tree, and update reviews. A malicious transitive dependency can't be fully defended.
Best-effort
A10
State-level actor
Boring vetted primitives, public spec. No claim against zero-days or hardware implants.
Best-effort
A13
Traffic analysis
Sync timing and blob sizes are visible. Padding and cover traffic deferred beyond v1.
Best-effort
A12
Coerced user ("rubber-hose")
No plausibly-deniable encryption in v1. If compelled to enter your password, the data is exposed.
Out of scope

Not protected against

You lose both password and phrase

Unrecoverable. We cannot help — no reset, no backdoor.

Malware running as you

A keylogger reads your password; a scraper reads decrypted notes. No user-mode app defends this.

Coercion to enter your password

No plausibly-deniable encryption in v1. The data is exposed.

Files you export

Exported markdown or PDF is ordinary unencrypted. Myne protects what it stores, not what you take out.

The spec layer

Read the documents.

The full normative specification, public in the repository. Changes ship as drafts with a review period before they reach production clients.

protocol.md The at-rest encryption protocol — key hierarchy, AEAD, recovery, blob formats. normative
threat-model.md Adversaries, assets, trust boundaries, and what is explicitly out of scope. normative
account-number.md The Crockford base32 + Damm-32 account-number format and validation. normative
recovery-flow.md The recovery-phrase presentation, confirmation, and re-key flow. normative
markdown-dialect.md The exact markdown Myne renders, including the safe-HTML allowlist. normative
wikilink.md Wikilink syntax, path encoding, resolution, and rename auto-update. normative