Skip to contentMenu Download OpenVireo

This page explains the pieces the SDK works with. The exact formats are in the protocol spec, SPEC.md; the section numbers below point into it.

Two servers

An OpenVireo account uses two servers:

  • The account server (the issuer, e.g. https://accounts.openvireo.com) knows accounts, devices, organisations, who may open which vault, and the encrypted keys that go with that. It hands out short-lived access tokens. It never sees a vault’s contents.
  • The sync server stores each vault as one encrypted .kdbx file. It checks the access token and nothing else, and it never sees a key. See the sync server docs.

Account.connect({ issuer }) finds both through the issuer’s discovery document, /.well-known/openvireo-configuration (§10).

Without an account, a self-hosted sync server works on its own, with a token per device and the database’s own password.

Master password and Secret Key

Signing in takes two secrets:

  • The master password, which the user remembers. It goes through OPAQUE (§8), a password protocol in which the account server never learns the password, not even at sign-up.
  • The Secret Key, 128 random bits made on the device at sign-up and shown as K1-XXXXXX-XXXXX-XXXXX-XXXXX-XXXXX (§2). The server never sees it. Users keep it in their Emergency Kit, and each trusted device keeps a copy, so they only type it once per device.

Together they make the Account Unlock Key (AUK): Argon2id over the password, then HKDF with the Secret Key (§3). A stolen password database on the server is useless without every user’s Secret Key.

Keysets

Every principal (a user, user:<uuid>, or a service account, sa:<uuid>) has a keyset: an X25519 key pair for encryption and an Ed25519 key pair for signing (§5). The private half is stored on the account server wrapped (encrypted, §4) with the AUK, and decrypted only on the device, in memory, while the account is unlocked.

The public half is signed. Before sealing anything to someone, the SDK checks that signature, and the share dialog shows their fingerprint so people can compare it out of band.

Vaults

A vault is one KDBX 4 file on the sync server, opened with a random 32-byte vault key instead of a password (§7). The key is sealed (§6) to the public key of everyone who may open the vault, and the account server stores those sealed copies. Vault names are encrypted with the vault key too, so the account server doesn’t learn them.

Each grant has a role:

RoleCan
readopen the vault
writealso change it
managealso share it, revoke access, rotate its key, rename and delete it

Removing someone from a vault rotates its key: a new key is sealed to everyone who stays, and the file is re-encrypted with it (§7). Old copies the removed person downloaded still open with the old key, so rotate the secrets inside too if that matters.

Organisations

An organisation owns shared vaults and service accounts. Members are owner, admin or member. Owners and admins get manage on every org vault; members get the vaults an admin picks. A new member is first invited (by email), then accepts, then an admin confirms them, which is when vault keys are sealed to their public key (§12).

Service accounts

A service account is a principal for automation, created inside an organisation with grants on some of its vaults. Its token, ov_sa_…, holds what it needs to decrypt its own keyset, so it works without a password or Secret Key (§9). Tokens can expire and be revoked, and an org can have several per service account. See Service accounts.

Secret references

An ov:// reference names one field in a vault (§14):

ov://<vault>/[<group>/…]<entry>/<field>
  • <vault> is a vault id, or a vault name that matches exactly one vault the principal can open.
  • Groups are matched by exact name, one level at a time from the root group.
  • <entry> is an entry UUID or a title that matches exactly one entry under that group (outside the Recycle Bin).
  • <field> is title, username, password, url, notes (any case) or a custom field’s name.
  • Each segment is percent-encoded: ov://Team%20Infra/Deploy/Database/password. A / inside a name is %2F.

Without the /<field> it names a whole entry, an item.

Sync and merge

Every write is a conditional upload: the client says which version it changed (If-Match with the ETag). If someone else uploaded in the meantime, the server answers 412, and the SDK downloads the new version, merges, and tries again. The merge is three-way, against the last version both sides had (the base copy), and matches the desktop app’s; see Merge behaviour. Concurrent edits are combined, not lost.

The SDK also refuses a server copy that is older than one it already synced (rollback protection), using a generation counter stored inside the encrypted file, so a server can’t quietly serve an old version.

What the servers see

Account serverSync server
Master passwordnever (OPAQUE)never
Secret Keynevernever
Keysetwrapped with the AUKnever
Vault keyssealed to each member’s public keynever
Vault namesencryptednever
Vault contentsneverencrypted .kdbx
Who may open which vaultyesfrom the access token
Email address, devices, org membershipyesno

The SDK docs cover OpenVireo SDK, develop (86e6cd2), last updated 26 October 2026. Found a mistake? Edit this page on GitHub.