Docs
  • 0.0.1latest

Keys and layers

The three layers a record passes through, the keys at each, the chain of vouching that decides who can be a reader, and the one key file the server holds.

A record is plaintext in one place only: the browser of a member it is shared with. Below the browser are two layers, and each holds keys of its own; none of them holds a key that opens a record.

Status. Release 0.0.1, the first.

The layers

  1. The browser seals each revision and wraps the record's key to its readers.
  2. The server keeps the sealed body in the company's own TessariDB vault, which opens only for a request presenting that company's key. The key is derived per request from the service key and never stored.
  3. TessariDB stores the vault encrypted again. The store's own vault passphrase and its root account open none of it, and a scan of a backup or the store directory finds no record body.

The browser's keys

KeyWhat it doesAlgorithm
unlock keywraps your private keys for one companyArgon2id, then HKDF-SHA256 and AES-256-GCM
agreement keyreceives record keys and group keys wrapped to youX25519, HPKE (RFC 9180)
signing keysigns the revisions you write and the statements you vouchEd25519
record keyone per record, wrapped to each member or group it is shared withrandom 256-bit
content keyseals one revision, once, bound to its company, record, revision and keyHKDF-SHA256, AES-256-GCM

The unlock key's derivation is checked before any work is done: at least 47 104 KiB of memory, 1 to 10 passes, 1 to 8 lanes. A wrapped key set that asks for less is refused rather than derived. The browser's cryptography carries no third-party code; HPKE is checked against the standard's published vectors.

Vouching

The company's first owner pins the company owner key. Owners and admins then append signed statements to a chain that starts at it, one member key or group key at a time, after comparing the key's fingerprint with its holder. A browser:

  • wraps a record key only to a key the chain covers, and
  • trusts a revision only from an author the chain covers.

The server stores the chain, but a statement not signed by a key the chain already covers is refused by every browser, so writing a row adds no reader.

The service key

The server reads one file at start: 32 random bytes as 64 hexadecimal characters, readable by its own user only. From it the server derives the key that opens each company's vault, the pepper applied to sign-in passwords before Argon2id, and the key that seals authenticator secrets. The file's contents are dropped from memory once those keys exist.

The file is not in the store, so a backup of the store holds none of these keys. Back it up apart from the store: without it the server can open nothing it keeps.

The web application

The pages and their script are compiled into the tessaridb-vault binary and served from it. Every page carries a content security policy that lets it run only its own script and its own WebAssembly, talk only to its own origin, and never be framed.