Montara Pass
Architecture

Encryption

The key hierarchy, the algorithms and what each key protects.

Key hierarchy

master password
   │  Argon2id (salt, 64 MiB, 3 passes)
   ▼
master key ──unwraps──► vault key ──unwraps──► private key (RSA)
                           │                        │
                           │ encrypts               │ unwraps
                           ▼                        ▼
                      folder names             item key (one per item)
                                                    │ encrypts
                                                    ▼
                                               item content
KeyMade fromProtectsWhere it is stored
Master keyArgon2id over the master passwordthe vault keynowhere; derived on unlock
Vault key32 random bytesfolder names, the private keyserver, wrapped by the master key
Key pairRSA-OAEP 3072-bititem keyspublic key in the clear; private key wrapped by the vault key
Item key32 random bytes, one per itemthat item's contentserver, once per member, wrapped by the member's public key

Algorithms

  • Key derivation: Argon2id with a 16-byte random salt, 64 MiB of memory, 3 iterations and parallelism 1, producing a 32-byte key. The parameters are stored next to the salt so they can be raised later. The API refuses anything below 19456 KiB and 2 iterations.
  • Symmetric encryption: AES-256-GCM. Every sealed value is a random 12-byte nonce followed by the ciphertext and its tag.
  • Asymmetric encryption: RSA-OAEP, 3072-bit modulus, SHA-256. The public key travels as SPKI, the private key as PKCS#8.
  • Encoding: every binary value is base64 in JSON.

Item content

The plaintext of an item is a small JSON object, sealed with the item key:

{
  "name": "GitHub",
  "username": "octocat",
  "password": "…",
  "url": "https://github.com",
  "notes": "…",
  "icon": "data:image/png;base64,…"
}

icon is optional: the extension adds the site's icon when a login is saved, and clients show it only when it is a PNG data URL. A secure note carries name and notes only. notes, of either type, are Markdown: the web app and the extension's full-screen view edit them as rich text, with headings, lists, quotes, code and inline formatting, and the extension's item detail renders them the same way. Notes written as plain text before that still read as they did: a line break stays a line break. An image in a note is shown as its Markdown and never loaded.

A secure note may also carry "visible": false. The extension then shows it blurred in the item's detail until Show note is pressed; the switch is in its item form. The flag is part of the encrypted content, so the server does not learn which notes are marked. It is a screen for the eyes, not a lock: the note is decrypted with the rest of the vault.

Every item also has a cipher_version in the clear (currently 1), so the format can change later without guessing.

Unlocking

  1. The client fetches the key set with GET /api/v1/keys.
  2. It derives the master key from the master password and the stored salt and parameters. This is the slow step, about a second.
  3. The master key opens the vault key; a wrong master password fails here, because AES-GCM rejects the tag.
  4. The vault key opens the private key.
  5. For each item, the private key unwraps the item key, which opens the content.

The web app keeps the unlocked keys in memory, so a reload locks the vault again. The extension keeps them in the browser's in-memory session storage; see Browser extension.

Changing the master password

Only the wrapping of the vault key changes. The client derives a new master key with a fresh salt, re-wraps the same vault key and sends it with PUT /api/v1/keys. No item and no folder is re-encrypted.

There is no recovery

The server never holds anything that can open the vault key. A forgotten master password means the vault cannot be read by anyone.

On this page