Skip to main content

AliasVault Security Whitepaper

Security architecture, cryptographic design and threat model

Version 0.5 (draft), 2026-10-18. Applies to AliasVault 0.31.0 and later. See Document information.

This document describes how AliasVault protects user data: which keys exist, where they are created and stored, how clients authenticate, how personal vaults, shared vaults and emails are encrypted, and what the server can and cannot do. It covers the cryptographic design of all clients and the server, the threat model and the known limitations. It does not cover the operational security of AliasVault Cloud or any other deployment, or the security of the platforms the clients run on. The source code is the final reference and is linked from Appendix A.

1. Architecture overview​

AliasVault Security Architecture DiagramAliasVault Security Architecture Diagram

AliasVault is a password and email alias manager with end-to-end encryption. It stores credentials, passkeys, TOTP secrets, notes, identities and attachments in a vault that is encrypted on the user's device, and it runs its own email server so that every alias address receives mail that is stored encrypted for the vault the alias belongs to. It consists of:

  • Server: a .NET API, an admin portal, an SMTP service and a task runner, backed by PostgreSQL. The server stores encrypted vaults and emails, routes mail to aliases, authenticates users and keeps the metadata needed to do so.
  • Clients: a web app, browser extensions (Chrome, Firefox, Edge, Safari) and native iOS and Android apps.
  • Rust core: one library, compiled to WebAssembly for the web app and the extensions and to native libraries for iOS and Android, that implements key derivation, key encryption, signing, SRP, the vault format, sync and merge, passkeys and the email parser. Every client runs the same cryptographic code.

All of it is open source under the AGPL-3.0 license in one repository: github.com/aliasvault/aliasvault. The same code runs as AliasVault Cloud (app.aliasvault.com), operated by the AliasVault team, and as self-hosted instances. In this document "the server" means whichever of the two a user's clients talk to, and "the server operator" means the party running it; the threat model treats the server as untrusted in both cases.

"Zero-knowledge" is used in one sense: the server never holds a key that decrypts a vault, and never receives vault contents in a form it can read. Vault contents are encrypted on the device before upload, incoming email is encrypted on arrival with the public key of the vault its alias belongs to, and a shared vault's key is stored only encrypted for each member's public key. Four things fall outside this definition and are stated in the threat model: the server handles each incoming email in plaintext for the moment it takes to encrypt it (2.2), the server keeps the metadata it needs to route mail and serve accounts (2.4), the web app's code is delivered by the server (2.2), and the public key a client encrypts a shared vault's key to when inviting a member is served by the server (13.2).

2. Threat model​

This section states what AliasVault protects, against whom, and under which assumptions. Each guarantee holds against a server that deviates arbitrarily from its expected behaviour (2.3), except where section 13 says otherwise.

2.1. Assets​

In order of value:

  1. The master password and the keys derived from it (the unlock key and the KEK).
  2. The Account Key, the Vault Encryption Keys, the account private keys and the vault delivery private keys.
  3. Vault contents: credentials, passkey private keys, TOTP secrets, notes, identities and attachments.
  4. The contents of emails received on aliases.
  5. API session tokens. They give access to encrypted data and to account actions, not to decryption.
  6. Metadata: usernames, alias addresses and the vault each belongs to, sharing relationships, vault sizes and change times, and authentication logs.

2.2. Trust assumptions​

The guarantees in this document hold under the following assumptions.

  • The device and its operating system are trusted. Everything AliasVault decrypts exists on the device while the vault is unlocked, so malware running with the user's privileges, a rooted or jailbroken device with hostile tooling, a keylogger, or an attacker reading process memory sees what the user sees. AliasVault hardens against this where the platform allows (section 11), but data on a compromised device is outside what it can protect. Locking the vault removes the decrypted vault and the keys from memory, so a device compromised after locking yields ciphertext only; in JavaScript hosts, memory clearing is best effort.
  • The client code is authentic. The user runs an unmodified AliasVault client obtained from an official channel. The browser extensions and the mobile apps are installed once, from the extension stores, the app stores, F-Droid, the GitHub releases or the official downloads website (downloads.aliasvault.com), and do not load code from the server, so a server that later turns malicious cannot change them. The web app, like every web application, loads its code from the server, which lets you reach your vault from any browser without installing software. For the web app, the server and the TLS connection are therefore trusted to deliver the published code; the browser extension and the mobile apps do not depend on this.
  • The master password is strong and secret. Anyone holding a copy of the user's encrypted data (the server database, device storage, an export) can run an offline guessing attack at the cost of one Argon2id derivation per guess, and there is no second secret mixed into the derivation. AliasVault requires at least 12 characters and shows a strength indicator, but the strength of the password is the user's choice.
  • The standard cryptography is sound. Argon2id, AES-256-GCM, RSA-OAEP, Ed25519, SRP-6a, HKDF and HMAC with SHA-256, and the platform's random number generator (WebCrypto in browsers, the system generator on iOS and Android).
  • Members of a shared vault are trusted with that vault. A member can read and copy everything in the vault. Removing a member stops their future access through the server; it cannot take back what they already synced (13.1).
  • TLS protects the transport, but vault confidentiality does not depend on it. The master password never crosses the wire (SRP), and vault data is encrypted before it is sent. A broken TLS connection exposes session tokens and metadata, which give API access but no decryption. The mobile apps do not pin certificates, to support self-hosted servers (13.6).
  • The server operator is trusted at the moment an email arrives. Email reaches the SMTP service in plaintext, as the protocol requires, and is encrypted in memory before it is stored. Email encryption therefore protects stored email against later access to the database, backups and the API, not against an operator who captures mail as it arrives. Transport from the sender to the SMTP service depends on the sender's use of STARTTLS, which the service offers when certificates are configured.

2.3. Threat actors​

The last column names the mechanism and the section that describes it.

AdversaryAssumed capabilitiesMust not be able toMechanism
Malicious or compromised server (operator, insider, intruder, leaked database or backups)Reads and modifies everything the server stores; controls every API response; serves any public key, setting or version it likesRead vault or stored email contents; learn the master password or any key; forge or alter vault contents undetected; move data between vaults, fields or users; make a client derive a key below the client-enforced minimumClient-held key hierarchy (4); AES-256-GCM bound to its slot (4.1, 6); signed public keys and grants (10); client-side Argon2id minimum (4); residual: key substitution at invitation (13.2), rollback (13.3) and email on arrival (13.4)
Network attacker (on-path, rogue access point, mis-issued certificate)Reads and modifies traffic between client and serverLearn the password or any key; read vault contents; impersonate the server to a client during loginSRP with mutual proof (5); vault data encrypted before transmission (6); TLS
Malicious website visited while the extension is installedRuns scripts in its own page, sends messages to the content script, calls the WebAuthn APIObtain credentials or passkey signatures for another site; trigger autofill for another origin; read extension storageAutofill matched on the registrable domain; WebAuthn origin and relying-party checks (8); content-script isolation, one item released per user pick
Another AliasVault user, including current and former shared-vault membersHolds their own account, grants they were given, and copies of data they syncedOpen a vault they were not invited to; read another user's personal vault; keep receiving a shared vault's mail after removalOne VEK per vault, grants only to invited accounts, per-vault authorization on the server, delivery keypair replaced on removal (10); residual: the VEK is not rotated (13.1)
Holder of a stolen session tokenCalls the API as the user until the token expires or is revokedDecrypt anythingTokens never decrypt; access tokens live 10 minutes; refresh tokens are stored hashed and rotated on use; sessions can be revoked (5.3)
Holder of a copy of the encrypted data (server database, device storage, backup, export file)Unlimited offline computationDecrypt without the master password or export passwordArgon2id with a client-enforced minimum (4, 12); residual: a PIN-protected copy on the device is only as strong as the PIN (13.7)
Sender of a crafted emailSends any content to any aliasRun code in a client; read anything from the vault; learn anything about the recipientParser in the memory-safe Rust core; HTML sanitized and rendered in a sandboxed frame without scripts; attachments never opened automatically (7)
Person with physical access to a locked deviceUses the device as foundUnlock without the master password, PIN or biometricsDevice unlock methods with attempt limits (11); anything beyond that is out of scope (2.5)

2.4. What the server knows and can do​

Stored in plaintext on the server:

  • Account: username, creation and last-activity times, the SRP salt and verifier, the Argon2id settings of each account unlock method, the TOTP secret and recovery codes when two-factor authentication is enabled, and lockout and block state.
  • Keys: public keys with their signatures; every private and symmetric key only in encrypted form (4.1).
  • Vaults: the ciphertext of manifests, data buckets and blobs, with manifest ids, revision numbers, sizes, upload times, ciphertext hashes and a limited history of older versions; the number of items in each vault, reported by the client for operational statistics; and the blobs each vault revision references, with their kind (attachment or logo).
  • Sharing: groups, their members and roles, which accounts hold a grant on which vault, and pending invitations.
  • Aliases: every alias address, the vault it belongs to, its state (active, paused, removed) and its creation time.
  • Email: the recipient alias, the time received, the sender's Date header, the attachment count and the ciphertext size (7.4).
  • Logos: the URL of an item whose logo is fetched through the server's favicon service.
  • Activity: an authentication log with the IP address, a country derived from it, device type, operating system, browser, time and outcome of every login attempt and security-relevant action; the pending Login with Mobile requests (9).

What the server can do:

  • Deny service, delete data and block accounts (2.5), and serve an older version of a vault, which clients do not detect (13.3).
  • Through the admin portal: see the metadata above, disable a user's two-factor authentication, block or delete an account, and within the retention period (7 days by default) revert a password change by restoring the previous encrypted Account Key, which it cannot read.
  • Present a public key and signing key of its own choosing when a client looks up another user's key for a sharing invitation (13.2).
  • Serve modified web app code (2.2).
  • Read an incoming email at the moment it arrives (2.2), and deliver an email of its own making to any alias.
  • Answer whether an alias address is taken, which anyone can also learn from the SMTP bounce for an unknown address.

What the server cannot do:

  • Read vault contents or stored email contents, or learn the master password, the unlock key, the KEK, the Account Key, any VEK, any blob key or any private key. The one exception is the VEK of a shared vault at the moment a member is invited (13.2).
  • Check a guess of the master password cheaper than one Argon2id derivation per guess: the SRP verifier and the encrypted Account Key cost the same, and the SRP input cannot be turned into the KEK.
  • Modify vault contents, or move ciphertext between vaults, data buckets, blobs or users, without the client refusing it.
  • Give anyone access to a vault: only a holder of the VEK can create a grant, and every grant is signed by the account that created it.
  • Learn passkey private keys or TOTP secrets stored in a vault, or produce passkey signatures.

2.5. Out of scope​

AliasVault does not defend against the following, and reports that depend on them are classified as hardening, not as security boundary failures (see SECURITY.md):

  • A compromised device: malware with the user's privileges, rooted or jailbroken devices with hostile tooling, kernel-level or runtime instrumentation, malicious accessibility services, memory dumps of a running client, and forensic extraction of device storage or backups.
  • A weak, reused or disclosed master password.
  • Social engineering where the app accurately presents the action and the user approves it.
  • Tampered client builds and compromise of the channels that deliver them (extension and app stores, F-Droid, GitHub, the user's browser), and vulnerabilities in the operating system, browser or hardware.
  • Availability. A malicious server can always refuse to serve or delete data; local copies and exports are the mitigation.
  • Hiding whether a username is registered. On a server with public registration, registration and the username availability check reveal it, rate limited per IP address. When registration requires an invite code, both require a valid code, and the login endpoint answers an unknown username with a substitute SRP response that stays the same across requests; a locked or blocked account still answers with its own error.
  • Side channels on the device, and traffic analysis beyond the metadata listed in 2.4.

3. Cryptographic algorithms​

AliasVault uses only established primitives standardized by NIST and the IETF; how they are combined is described in sections 4 to 12. The table lists each algorithm and where it is used.

AlgorithmUsed forSection
Argon2idDeriving keys from the master password, PIN and export password4, 11, 12
HKDF-SHA256Splitting the unlock key into the SRP input and the KEK4
SRP-6aPassword authentication without sending the password5
AES-256-GCMVault contents, blobs, emails, exports and every key in the hierarchy4.1, 6, 7, 9, 10, 11, 12
RSA-OAEPEmail encryption, Login with Mobile, vault sharing7, 9, 10
Ed25519Signing public keys, grants, delivery keys and invitations4.1, 7, 10
HMAC-SHA256Blob addresses, passkey PRF, session token (JWT) signing5, 6, 8
SHA-256Integrity checks and key fingerprints9, Vault Format and Sync
TOTPTwo-factor authentication5
ES256 / RS256Passkeys (WebAuthn)8

4. Key derivation and key hierarchy​

Your master password never leaves your device. It unlocks your Account Key, the key that opens all your vaults and that the server only ever stores in encrypted form. When you log in, it is also used to calculate a proof the server can check without knowing the password itself.

AliasVault key hierarchy diagramAliasVault key hierarchy diagram
  • Your master password is processed with Argon2id (a memory-hard key derivation function) on your device
    • Argon2id parameters used for the master password: 64 MiB memory, 5 iterations, parallelism 1, salt = the account's random 32-byte SRP salt (created on the client at registration and stored on the server)
    • The server sends the salt and the account's settings at login. The client refuses settings below a fixed minimum built into the Rust core (19 MiB, 2 iterations, parallelism 1, the parameters of the first public release, which older accounts keep until their next password change), which prevents a downgrade attack where a server would ask for a weaker key. The server in turn refuses to store a new unlock method, at registration or at a password change, with settings below the current defaults (64 MiB, 5 iterations).
  • The derived key is the unlock key. It is never used as-is; two keys are derived from it with HKDF-SHA256, each under its own label:
    • The SRP input (label AliasVault SRP v1), for authentication with the server through the SRP protocol
    • The Key Encryption Key (KEK, label AliasVault KEK v1), which decrypts the Account Key
  • The SRP input and the KEK are independent: neither can be calculated from the other, or back to the unlock key and the master password. Even if the value used for login were exposed (e.g. in logs), it would not reveal the key that decrypts the Account Key.

4.1. Key hierarchy​

Every unlock method (e.g. master password) opens the same Account Key, which unlocks a chain of random keys, all created on the client. Each vault has its own key, so giving a user access to a shared vault does not give them access to your personal vault or to other shared vaults:

KeyWhat it isWhat it protectsStored on the server as
KEK (Key Encryption Key)Derived from an account unlock method; for the master password, with HKDF-SHA256 from the unlock key (its Argon2id output)The Account KeyNever stored
AK (Account Key)Random 256-bit key, created at registrationThe personal VEK and the private keys of both account keypairsEncrypted with the KEK, one copy per account unlock method
VEK (Vault Encryption Key)Random 256-bit key, one per vault: the personal vault and any shared vaults have separate keysThe vault contents and its blob keysEncrypted with the owner's AK (personal vault) or with each member's account public key (shared vault)
Account encryption keypairRSA-2048 keypair, one per userPrivate key opens the VEKs of shared vaults this user is a member ofPublic key in plaintext (signed with the user's account signing key), private key encrypted with the AK
Account signing keypairEd25519 keypair, one per userSigns what the user publishes: their RSA public key, grants, delivery keys and the vault name in an invitationPublic key in plaintext, private key encrypted with the AK
Vault Delivery KeypairRSA-2048 keypair, one per vaultPrivate key opens emails for aliases in that vaultPublic key in plaintext, private key stored inside the encrypted vault
Blob keyRandom 256-bit key, one per blob (content stored separately from the rest of the vault, such as the bytes of an attachment or logo)That blob's bytesEncrypted with the VEK of the vault the blob belongs to

Key vs keypair: a key is a single secret used to encrypt and decrypt (AES-256-GCM). A keypair has a public key that can be shared openly to encrypt or verify, and a private key that decrypts or signs and is only stored encrypted.

All symmetric encryption in this chain uses AES-256-GCM, all asymmetric encryption uses RSA-OAEP with SHA-256. Every ciphertext is bound to its place with AES-256-GCM associated data or an RSA-OAEP label (aad.rs), so a ciphertext taken from one slot does not decrypt in another and a vault served under another vault's id is refused.

Properties of this hierarchy:

  • Password change only encrypts the Account Key (AK) again with the new KEK. Vault contents, attachments and shared vault access stay unchanged, so nothing has to be re-encrypted or uploaded and shared vault members are not affected. The user's other devices are signed out and log in again with the new password. The user can choose to also replace the keys themselves (4.2).
    • Undoing a password change: the previous encrypted Account Key is kept on the server for 7 days, so an administrator can restore the old password when a user cannot log in with the new one. The server cannot decrypt it; a revert only restores the old password, signs out all sessions of the account and is written to the server log. A revert is refused once the keys have been rotated after that password change. The server operator sets the retention period, and 0 turns it off.
  • Device unlock methods (biometrics, PIN, passkey quick unlock) keep their own encrypted copy of the Account Key on the device only, protected by the device keychain, a PIN-derived key or a passkey PRF key, never the password-derived keys. Login with Mobile hands the Account Key over once, encrypted with a one-time RSA key. They keep working after a password change and are set up again after a key rotation. Every unlock walks the same chain from the Account Key down, so all keys below it always become available together.
  • Additional account unlock methods can be enabled by encrypting the same Account Key with another KEK, without having to re-encrypt the vault or invalidating existing unlock methods.

4.2. Key rotation​

When you change your master password, you can choose to also replace all encryption keys of your account. Without it, a password change keeps the keys (4.1).

  • Replaced: the Account Key, the personal VEK, both account keypairs and the personal vault's Vault Delivery Keypair, all created on the client. The new signing key is signed with the old one.
  • Re-encrypted: the personal vault and its blob keys with the new VEK, and every grant the user holds for the new account public key. The previous VEK is kept, encrypted with the new Account Key.
  • Unchanged: blob bytes, shared vault VEKs and received emails, whose old delivery keypair stays in the vault.
  • All or nothing: the server applies the rotation in one transaction and refuses it when a blob key or grant is missing or the vault changed in the meantime.
  • Other devices: a rotation only starts when no other session is active. Devices still on the old keys are signed out, device unlock methods have to be set up again, and pending invitations to the user are closed.
  • Scope: the old keys cannot decrypt anything written to the personal vault after the rotation. Older vault revisions, received emails and shared vaults stay under their existing keys (13.1).

5. Authentication process​

Your master password is never sent to the server. Instead, during login, client and server authenticate each other with the SRP protocol: the client proves it holds the key derived from your password, and the server proves it holds the matching verifier, without either side sending its secret. When two-factor authentication is enabled, the server also checks a TOTP code before it issues API session tokens. These tokens give access to your account on the server, but can never decrypt your vaults.

AliasVault authentication diagramAliasVault authentication diagram

5.1. SRP login​

  • SRP-6a with the 2048-bit group of RFC 5054 and SHA-256; the password itself is never sent
  • The SRP identity is a random per-account id, so a username change does not change the verifier
  • Client and server each prove they derived the same session key; the client checks the server's proof before accepting any token

5.2. Two-factor authentication​

  • Optional: when enabled, a TOTP code from a standard authenticator app is required after the SRP step
  • The server only issues session tokens after the code is verified
  • Two-factor authentication protects access to the account on the server. It is not part of the encryption: the TOTP secret and the recovery codes are stored on the server, and a vault is still protected by the master password alone

5.3. Session tokens​

  • A short-lived JWT access token (10 minutes, signed with HMAC-SHA256) and a refresh token (8 hours by default, 14 days when the user chooses to stay logged in; both configurable by the server operator). The refresh token is stored hashed on the server, so a database leak does not expose usable tokens, and is rotated on every use, so a copied refresh token stops working once the legitimate client refreshes
  • Tokens grant API access only; they never decrypt anything
  • The user can see their active sessions and authentication log in the security settings of the clients and revoke any session

5.4. Brute-force protection​

  • After 10 failed login attempts an account is locked for 30 minutes
  • Registration, Login with Mobile, logo fetching and alias availability checks are rate limited per account and per IP address, and the server operator can block IP ranges
  • Every login attempt and security-relevant action (password change, key rotation, two-factor changes, logout, shared vault creation and deletion, account deletion) is written to the authentication log with the IP address and client details

6. Vault operations​

Your vaults are always encrypted on your device before they are uploaded. Each vault (your personal vault and every shared vault) is stored on the server as one encrypted manifest, plus separate data buckets and blobs. The server only receives and stores these in encrypted form and can never read their contents.

AliasVault vault storage format diagramAliasVault vault storage format diagram
  • Vault contents are encrypted and decrypted on the device with AES-256-GCM and only reach the server encrypted
  • The encryption key is the vault's VEK (see Key hierarchy), not the master password itself
  • Each manifest is encrypted with the VEK of its vault and bound to its manifest id, so the server cannot swap one vault's data for another's. Data that changes often, such as UI settings and usage statistics, is kept in separate data buckets that sync on their own, so a small change like a different sort order does not require uploading all items again; how a vault is split into manifests, data buckets and blobs is described in Vault Format and Sync.
  • Some content, such as the bytes of attachments and logos, is stored outside the manifest as separate blobs, each encrypted with its own random blob key; the blob key is encrypted with the VEK of the vault the blob belongs to. A blob is addressed by HMAC-SHA256(manifest salt, plaintext), where the manifest salt is a random value that lives inside the encrypted manifest, so the server cannot recognize the same file across vaults while every member of a shared vault computes the same address
  • On the device, the vault is only decrypted in memory while it is unlocked. The copy kept on disk stays encrypted with the VEK, together with the encrypted key hierarchy, so a device can unlock offline
  • The server keeps a limited number of older versions of each manifest and data bucket as a backup against potential client-side data corruption. Blobs never change; a blob is deleted once no kept version refers to it anymore

7. Email​

AliasVault encrypts each incoming email in memory as soon as it arrives, with the delivery public key of the vault the alias belongs to, and only writes its content to the database in encrypted form. Only people with access to that vault hold the private key and can read its emails.

AliasVault email encryption diagramAliasVault email encryption diagram

7.1. Key generation and storage​

  1. Every vault (personal or shared) has its own Vault Delivery Keypair (RSA-2048), generated locally on the client
    • The private key is stored inside that encrypted vault
    • The public key is sent to the server together with the vault, signed with the publishing user's account signing key; the server only accepts a key signed by a member allowed to publish it
  2. Each alias is registered on the server as an email claim, which links the alias to the vault it belongs to
  3. When a member loses access to a shared vault, the Vault Delivery Keypair is replaced, so future emails are encrypted to a new key. Old keypairs are kept in the vault, so emails received before the change stay readable

7.2. Email reception process​

  1. When an email is received, the server:
    • Checks whether the recipient address matches an active email claim
      • If there is none, the email is rejected
    • Generates a random 256-bit symmetric key
    • Encrypts the email content (subject, sender fields, bodies, preview, raw source and attachments) using this symmetric key with AES-256-GCM
    • Encrypts the symmetric key with the delivery public key of the vault the claim belongs to (RSA-OAEP)
    • Stores the encrypted email and the encrypted symmetric key

7.3. Email retrieval process​

  1. The client retrieves the encrypted email and the encrypted symmetric key
  2. The client decrypts the symmetric key with the delivery private key of the matching vault
  3. The client decrypts the email contents with the symmetric key
  4. All decryption occurs locally on the client device
  5. The email is parsed by the Rust core, its HTML is sanitized, and it is shown in a sandboxed frame that cannot run scripts

7.4. What the server sees​

  • Email is end-to-end encrypted from the moment it is stored, not from the sender: the SMTP service sees each message in plaintext while it encrypts it (2.2). Transport from the sender is protected only if the sender uses STARTTLS
  • The recipient alias, the time received, the sender's Date header, the attachment count and the ciphertext size stay in plaintext, so the server can list and expire mail without decrypting it. The alias-to-vault mapping is plaintext because the server needs it to route mail
  • Email content is untrusted input. Anyone can send to an alias, so the encryption proves nothing about who wrote a message; the clients treat every email as hostile content

8. Passkey authentication​

Your passkeys are stored in your vault and encrypted like the rest of its contents. AliasVault acts as the passkey authenticator (WebAuthn Level 2): it creates each passkey's keypair, keeps the private key in your vault, and only gives websites the public key and signatures. You can use your passkeys in every AliasVault app that supports them.

AliasVault passkeys diagramAliasVault passkeys diagram

8.1. Virtual authenticator implementation​

  • The authenticator logic (key generation, authenticator data, attestation, signatures and PRF) is implemented once in the Rust core and shared by every app
  • Browser extension: intercepts navigator.credentials on the page and checks the website against the page's origin (Public Suffix List rule plus WebAuthn Related Origin Requests) before calling the core
  • iOS: credential provider extension (AuthenticationServices) calling the core
  • Android: Credential Manager provider service calling the core

8.2. Passkey registration process​

When a website asks to create a passkey:

  • The client creates a new keypair, ES256 (ECDSA P-256) or RS256 (RSA-2048), whichever comes first in the website's list of accepted algorithms
  • The private key is saved as part of the vault, so it is encrypted and synced like any other vault content
  • The website receives the public key in an attestation object with AliasVault's AAGUID (a11a5faa-9f32-4b8c-8c5d-2f7d13e8c942) and the flags UP (user present), AT (attested credential data), BE (backup eligible) and BS (backed up), plus UV when the user was verified
  • The attestation format is "none" or "packed" self-attestation, and the sign count is always 0, as is usual for passkeys that sync between devices

8.3. Passkey authentication process​

When a website asks to sign in with a passkey:

  • The client takes the passkey from the unlocked vault and signs the website's challenge with its private key
  • Only the signature is sent to the website; the private key never leaves the client

8.4. PRF extension​

  • Passkeys support the WebAuthn PRF extension (hmac-secret), which lets a website derive a stable secret from a passkey, for example to encrypt its own data
  • When a website asks for PRF at registration, a random 32-byte secret is created and saved in the vault with the passkey; for each salt the website sends, the client returns HMAC-SHA256(secret, SHA-256("WebAuthn PRF" || 0x00 || salt))

9. Login with Mobile​

You can log in to the web app or browser extension by scanning a QR code with the AliasVault mobile app, without typing your master password. The device you log in on creates a one-time keypair. The mobile app encrypts your Account Key with it and sends it to that device via the server, so only these two devices can read it.

AliasVault login with mobile diagramAliasVault login with mobile diagram

9.1. What passes through the server​

Two pieces of data travel through the server, both encrypted for the one-time public key of the device you log in on:

  • The Account Key, encrypted by your phone with RSA-OAEP
  • The new session tokens and account details, encrypted by the server with a random AES-256-GCM key, which is itself encrypted with RSA-OAEP

9.2. Login flow​

  1. Initiation (requesting client: web app or browser extension)

    • Client generates a one-time RSA-2048 keypair locally, only for this login request
    • Public key is sent to the server
    • Server creates a unique request ID and a poll secret, stores the public key and only a hash of the poll secret
    • Client generates a QR code containing the request ID and a SHA-256 hash of the public key
    • Client shows a 2-digit verification code derived from the public key
    • The one-time private key only exists in memory for the duration of this login request: it is never stored on disk or in a vault
  2. QR code scan (mobile app)

    • User scans the QR code with their authenticated mobile app
    • Mobile app retrieves the public key and requester details (browser, OS, IP address) from the server and checks the public key against the hash in the QR code
    • User picks the verification code shown on the requesting screen out of four options, approves, and confirms with biometrics or PIN
    • Mobile app encrypts the user's Account Key with the one-time public key generated by the requesting client (RSA-OAEP)
    • Encrypted Account Key is sent to server
    • Server temporarily stores the encrypted Account Key and marks the request as fulfilled
  3. Polling and retrieval (requesting client)

    • Client polls the server every few seconds with its poll secret
    • When fulfilled, server:
      • Creates a new session for the user: a JWT access token and refresh token that give the requesting client access to the API, similar to a password login (see Authentication process)
      • Creates a random 256-bit symmetric key
      • Encrypts the JWT tokens, username and the account's Argon2id settings with this symmetric key (AES-256-GCM)
      • Encrypts the symmetric key itself with the requesting client's one-time public key (RSA-OAEP)
      • Returns all encrypted data in the response
      • Immediately marks the request as retrieved and deletes the stored one-time public key and encrypted Account Key from the database
  4. Decryption (requesting client)

    • Client decrypts the Account Key and the symmetric key with its one-time private key
    • Client decrypts the JWT tokens, username and Argon2id settings with the symmetric key
    • Client unlocks the rest of the key hierarchy with the Account Key, as with a password login
    • The one-time private key is discarded from memory

9.3. Request binding and lifetime​

  • Bound to the requesting client: the QR code holds a hash of the one-time public key, which the mobile app checks, so the server cannot swap in a key of its own. The verification code the user picks in the mobile app is derived from the same key, so a request started by someone else is not approved by accident.
  • Only the requesting client gets the result: retrieving it requires a poll secret that the server hands only to the requesting client and stores only as a hash. Someone who sees the QR code or has a copy of the database therefore cannot retrieve it.
  • Short-lived and one-time: a request must be approved within 3 minutes and retrieved within 1 minute after that, it can be retrieved only once, and expired requests are cleaned up by the server.
  • The user is the last check: the mobile app shows the requester's client, operating system, IP address, location and the time the request was made, and warns with a delay when the request was opened from a link instead of the in-app scanner. Approving a request the user did not start hands the Account Key to whoever started it (2.5).

10. Vault sharing​

You can create a shared vault and invite other people to it, for example a family member. A shared vault is separate from your personal vault and has its own VEK, so members never get access to your personal vault or your master password. Each member receives the shared vault's VEK encrypted for their own account, so the server only stores encrypted copies of it.

AliasVault vault sharing diagramAliasVault vault sharing diagram

Shared vaults belong to a group, for example a family. A group has admins, who create shared vaults and invite people, and members.

Access to a shared vault is called a grant: a copy of the vault's VEK encrypted with one member's account public key, which only that member's account private key can decrypt. Every member, the creator included, has their own grant; the server stores the grants but cannot open them.

10.1. Sharing flow​

  1. Creation

    • A group admin creates the shared vault on their client
    • The client generates a new VEK and a Vault Delivery Keypair for the vault
    • The admin's own grant is created: the VEK encrypted with the admin's account public key (RSA-OAEP), signed with the admin's account signing key
    • The vault name is encrypted with the VEK, so only members can read it; the server never sees the name of a shared vault
  2. Invitation

    • The admin's client retrieves the invitee's account public key from the server and checks that it is signed by the invitee's account signing key
    • The shared VEK is encrypted with that public key and the grant is signed; the vault name is also encrypted with that public key and signed, so the invitee can see which vault they are invited to before accepting
    • The server verifies the signatures and stores the encrypted VEK with the invitation
  3. Acceptance

    • When the invitee accepts, the encrypted VEK from the invitation becomes their grant
    • From the next sync on, the server includes the shared vault (its encrypted manifest and the member's grant) because the grant is active
    • Their client checks the grant's signature, decrypts the VEK with their account private key, and with it the shared vault, which they can then read and write
  4. Revocation

    • Removing a member deletes their grant on the server
    • The server asks an admin's client to replace the Vault Delivery Keypair, so new emails are no longer encrypted to a key the removed member has seen
    • The server no longer provides the shared vault to the removed member, so their access is blocked. The vault keeps its VEK, so the remaining members are not affected

10.2. Access and keys​

  • Group membership alone gives no access: a group itself holds no keys, and being a member of a group does not open its shared vaults. A user only gets access to a shared vault after being invited to that vault and accepting, which gives them their own grant.
  • Each key has one job: the account encryption keypair only receives vault keys, and a Vault Delivery Keypair only decrypts email, so a key stored inside a vault never opens anything outside it.
  • Grants are tied to their vault: a grant is encrypted under a label that names the vault, so it cannot be used for another vault.
  • Grants and keys are signed: a grant, a published account public key and a published delivery key each carry an Ed25519 signature by the account that created it, over a message that names its purpose, so a grant cannot be created by someone who merely knows a public key, and a signature made for one purpose does not verify for another. The server checks every signature on upload; clients also check a grant before using it and the invitee's public key before encrypting for it. What the signature does not establish is who owns the signing key: that key is served by the server (13.2).
  • Enforcement layers: access to a vault's contents is enforced by cryptography (no grant, no key). Which vaults the server lists for a user, group membership and roles are enforced by the server. A few guards, such as refusing to delete the folder that represents a shared vault, are enforced only in the client.

11. Protecting keys on the device​

AliasVault gives you offline access to your data: each device keeps an encrypted copy of your vault together with the encrypted key hierarchy, so once it has synced you can unlock your vault without the network. You can unlock with your master password or a quicker method such as biometrics or a PIN; each method protects a copy of your Account Key that is stored only on that device, and the keys below it are then opened from the encrypted key hierarchy.

AliasVault keys on the device diagramAliasVault keys on the device diagram
  • Master password: the unlock key is derived with Argon2id from the salt and settings cached on the device, the KEK is derived from it with HKDF-SHA256, and the KEK decrypts the Account Key (see Key derivation and key hierarchy).
  • Biometrics (mobile): the Account Key is encrypted with a key held by the device's secure hardware. iOS uses a Keychain item with kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly and the biometryCurrentSet access control; Android uses an AndroidKeyStore AES-GCM key with setUserAuthenticationRequired(true), AUTH_BIOMETRIC_STRONG and setInvalidatedByBiometricEnrollment(true).
  • PIN (mobile and browser extension): the Account Key is encrypted with AES-256-GCM under a key derived from the PIN with Argon2id (random 16-byte salt, 64 MiB, 3 iterations). The PIN encryption and the attempt policy are implemented once in the Rust core; after 4 failed attempts the encrypted Account Key is deleted and PIN unlock is disabled. A PIN has at least 6 digits. The browser extension stores the result in the extension's local storage; the mobile apps encrypt it once more with a key from the iOS Keychain (this-device-only) or the Android Keystore.
  • Passkey quick unlock (web app): the Account Key is encrypted with a key obtained from a passkey's PRF extension and stored in the browser.

Locking the vault removes the decrypted vault and the Account Key from memory; the encrypted vault stays on the device, so the next unlock can work offline. Logging out instead removes all data from the device, including the encrypted vault and key hierarchy, so logging back in requires a connection to the server.

On Android, the app is excluded from system backups (allowBackup="false"), so the encrypted vault and the encrypted keys are not copied to cloud backups. On iOS the Keychain items are marked as this-device-only.

12. Vault exports​

The recommended export format is an encrypted .avex file, which can be imported into AliasVault again. It contains all vault data, including attachments and logos, encrypted with AES-256-GCM under a key derived with Argon2id (256 MiB, 3 iterations, parallelism 1, random 16-byte salt) from an export password you choose. The salt and Argon2id settings are stored in the file's header, so the password alone is enough to open it again.

AliasVault vault exports diagramAliasVault vault exports diagram

AliasVault also offers two unencrypted formats, to export your data and import it somewhere else. Anyone who gets access to these files can read them, so use them with caution and delete them when you no longer need them:

  • .avux: the same ZIP archive as inside an .avex file, without the encryption
  • CSV: your items as plain text, for use in other tools

13. Known limitations​

These are the known limitations of the current design relative to the threat model, including trade-offs made on purpose. Each entry states what an attacker must already have for it to apply, what it allows, and what mitigates it today. Apart from the web app's code delivery (13.5), none of them lets the server read a personal vault without the master password. A limitation that is not listed here should be reported (section 14).

  1. Removing a member from a shared vault ends their access, but keeps the vault's key. The server stops serving the vault to the removed member, their client deletes its copy, and new email is encrypted to a new delivery key. The VEK stays the same, so the other members are not affected. Only if the removed member later obtains the vault's ciphertext outside the API, from a leaked copy of the server database, could they decrypt it with the VEK they had, including email received after their removal. To fully separate a vault from a former member, create a new shared vault, move the items to it, invite the remaining members, delete the old vault, and change the passwords the former member had access to. The new vault has its own VEK and keypair.
  2. Other users' public keys are provided by the server. Grants, account public keys and delivery keys are signed with the publishing account's Ed25519 key, which ties each of them to an account and prevents forged grants. The signing public key itself is served by the server and is not yet verified out of band. This leaves one opening, limited to the moment of sharing: a server that is actively malicious when an invitation is created can present a public key and signing key of its own and obtain the VEK of the vault being shared. Personal vaults and grants that already exist are not affected. Closing this gap requires out-of-band verification, such as a fingerprint phrase compared by both parties, or key transparency. Planned: a fingerprint shown at invitation and acceptance, and pinning of keys once seen.
  3. Clients do not detect an older vault revision being served as current. This affects freshness, not confidentiality or authenticity: the server can only serve a revision that members of the vault wrote earlier, and cannot read, change or create one (2.4). A client accepts such a revision as current, so changes made after it are lost and older states of items return. The effect is that of the server deleting data, which it can already do (2.5). This is a deliberate trade-off: a server restored from a backup after a failure serves older revisions in the same way, and a client that refused them would lock its user out of their vault.
  4. Email is encrypted at rest, not end to end from the sender. SMTP delivers mail in plaintext, so the SMTP service sees each incoming email before encrypting it (2.2), the recipient alias and timestamps stay in plaintext (7.4), and the server knows which vault owns which alias. Whether an alias address exists can be learned by anyone, by sending to it or by the availability check; what cannot be learned is who owns it. The database, backups and the API only hold encrypted email.
  5. The web app loads its code from the server. This is how every web application works, and it is a deliberate trade-off: the web app gives access to your vault from any browser, including on devices where you cannot install software, and in return relies on the server to deliver the published code over TLS. The browser extension and the mobile apps are installed once from official channels and do not load code from the server, so they do not depend on this (2.2).
  6. TLS settings allow self-hosted servers. The mobile apps do not pin certificates, and Android accepts user-installed certificate authorities and cleartext HTTP. Both are deliberate, so that self-hosted servers with private certificate authorities or local addresses work. Cleartext HTTP is only used when the user configures a server URL that starts with http://. Vault confidentiality does not depend on TLS; session tokens and metadata do.
  7. PIN unlock in the browser extension relies on the strength of the PIN once its storage has been copied. PIN unlock is optional. The copy of the Account Key protected by a PIN is encrypted under a key derived from the PIN with Argon2id, and the 4-attempt limit applies to guesses made through the extension. An attacker who has copied the extension's storage, which requires forensic access or a compromised device (2.5), is not bound by the limit and can try every 6-digit PIN at the cost of one Argon2id derivation per guess. On mobile, the PIN-encrypted Account Key is also encrypted with a device-bound key from the iOS Keychain or the Android Keystore, so a copy of the app's storage alone is not enough to start guessing. Use biometrics or the master password where this matters.
  8. Public-key encryption uses RSA-2048, not yet a post-quantum algorithm. Grants, email keys and Login with Mobile use RSA-2048-OAEP. An attacker who keeps a copy of that ciphertext (from the server database or captured traffic) could decrypt it once a quantum computer able to break RSA-2048 exists, and with it the shared vault keys, emails and Account Keys it protects. RSA-2048 provides 112-bit security, which NIST SP 800-57 Part 1 approves through 2030; the NIST draft transition plan (IR 8547) sets 2035 for moving public-key encryption to post-quantum algorithms. Vault contents and the keys that protect the personal vault at rest use AES-256-GCM, which is considered safe against quantum computers. Every RSA ciphertext carries an algorithm identifier, so a post-quantum scheme can be added next to RSA without breaking existing data; it will be added once well-reviewed implementations exist on every platform AliasVault supports.
  9. Clearing keys from memory depends on the platform. An attacker who can read the memory of a client while the vault is unlocked, or shortly after locking in a browser, may find copies of keys. Keys cross the WebAssembly and native boundaries as strings, and JavaScript runtimes do not offer a way to guarantee memory is cleared, so a copy may remain until the runtime reuses that memory. The Rust core zeroizes keys after use where possible, and locking drops every reference to the decrypted vault and the keys. Reading process memory requires a compromised device, which is outside the threat model (2.2).
  10. Argon2id settings are served by the server and not yet authenticated by the client. The client-side minimum (section 4), which equals the Argon2id configuration recommended by OWASP, stops a downgrade below the first release's parameters, but a server can still serve settings between that minimum and the current defaults to an account that was created with stronger ones. The key derived with those settings does not decrypt the account's Account Key, so the unlock fails; what a malicious server gains is a login attempt it can use to test password guesses at the cost of the weaker settings instead of the account's own. Raising the client minimum to the current defaults is planned.

14. Security assurance and disclosure​

  • Open source. The server, every client and the Rust core are developed in one public repository under the AGPL-3.0 license. The browser extensions and the Android app (via F-Droid) are built from that source; the releases on GitHub are tagged.
  • Independent review. AliasVault runs a public responsible disclosure program and has received and fixed reports from independent researchers since 2025; the advisories are published as GitHub security advisories and the reporters are credited on the responsible disclosure page. As of October 2026, preparations for an independent security audit of the cryptographic design and the Rust core are in progress; the report and our response will be published on this page once the audit is complete, expected before the end of January 2027.
  • Reporting a vulnerability. Email security@aliasvault.com. SECURITY.md states what to include, how reports are classified against the threat model of this document, when a CVE is requested, and the disclosure timeline; a machine-readable security.txt points to the same policy.
  • Supported versions. Security fixes are applied to the latest release only.

Appendix A. Implementation map​

Where each part of this document lives in the repository, for reviewers.

AreaLocation
Argon2id and the HKDF split into SRP input and KEKcore/rust/src/crypto/argon2.rs, core/rust/src/crypto/key_chain.rs
Key encryption (AES-256-GCM) and the associated-data labelscore/rust/src/crypto/aes_gcm.rs, core/rust/src/crypto/aad.rs, core/rust/src/crypto/key_chain.rs
SRP client and servercore/rust/src/crypto/srp.rs, apps/server/Utilities/AliasVault.Cryptography/Srp.cs, apps/server/AliasVault.Api/Controllers/V2/AuthController.cs
RSA-OAEP and JWK handlingcore/rust/src/crypto/rsa_oaep.rs, core/rust/src/crypto/jwk.rs
Ed25519 signing and verificationcore/rust/src/crypto/signing.rs, apps/server/Utilities/AliasVault.Cryptography/Signing.cs
Key rotationcore/rust/src/crypto/key_chain.rs, core/rust/src/vault_sync/rotation.rs, apps/server/AliasVault.Api/Controllers/V2/KeyRotationController.cs
PIN encryption and attempt policycore/rust/src/crypto/pin.rs
Vault format: canonicalize, materialize, integritycore/rust/src/vault_codec/
Sync engine: pull, push, grants, sharing, delivery keyscore/rust/src/vault_sync/
Merge of concurrent changescore/rust/src/vault_merge/
Passkeys (WebAuthn authenticator)core/rust/src/passkey/
Email parsing and HTML sanitizingcore/rust/src/email_parser/, core/client/src/email/EmailHtmlSanitizer.ts
Email encryption on receiptapps/server/Utilities/AliasVault.Cryptography/EmailEncryption.cs, apps/server/AliasVault.SmtpService/
API: authentication, vault, sharing, email, Login with Mobileapps/server/AliasVault.Api/Controllers/V2/
Session tokensapps/server/AliasVault.Api/Services/TokenService.cs
Device key storageiOS apps/mobile-app/ios/NativeVaultManager/, Android apps/mobile-app/android/app/src/main/java/net/aliasvault/app/vaultstore/, extension apps/browser-extension/src/utils/PinUnlockService.ts
Encrypted exportcore/client/src/transfer/export/AvexExportService.ts
Logo fetchingcore/client/src/items/FaviconService.ts, apps/server/Utilities/AliasVault.FaviconExtractor/

Appendix B. Glossary​

TermMeaning
Unlock keyThe Argon2id output of the master password. Never used directly.
KEKKey Encryption Key: derived from the unlock key with HKDF, decrypts the Account Key.
Account Key (AK)Random key that opens everything the account owns: the personal VEK and the account private keys.
VEKVault Encryption Key: random key of one vault, personal or shared.
ManifestThe encrypted document on the server that holds one vault's items.
Data bucketA separately encrypted part of a vault for data that changes often.
BlobThe encrypted bytes of one attachment or logo, with its own key.
GrantA vault's VEK encrypted for one member's account public key, signed by the account that created it.
Vault Delivery KeypairThe RSA keypair of a vault that incoming email is encrypted to.
Email claimThe server-side record that an alias address belongs to a vault.
GroupA set of accounts that can hold shared vaults; a group holds no keys.
Account unlock methodA server-stored copy of the Account Key under a KEK; today the master password.
Device unlock methodA device-only copy of the Account Key protected by biometrics, a PIN or a passkey.

References​

  • RFC 9106, Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications
  • RFC 5869, HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
  • RFC 2945 and RFC 5054, The SRP Authentication and Key Exchange System and Using SRP for TLS Authentication (group parameters)
  • NIST SP 800-38D, Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM)
  • RFC 8017, PKCS #1: RSA Cryptography Specifications Version 2.2 (RSA-OAEP)
  • NIST SP 800-57 Part 1 Rev. 5, Recommendation for Key Management: Part 1, General
  • NIST IR 8547 (initial public draft), Transition to Post-Quantum Cryptography Standards
  • RFC 8032, Edwards-Curve Digital Signature Algorithm (EdDSA)
  • RFC 6238, TOTP: Time-Based One-Time Password Algorithm
  • W3C, Web Authentication: An API for accessing Public Key Credentials Level 2
  • RFC 9116, A File Format to Aid in Security Vulnerability Disclosure (security.txt)

Document information​

Document version0.5 (draft)
AuthorAliasVault
Date2026-10-18
Applies toAliasVault 0.31.0 and later (vault format v1)
StatusDraft, pending independent review
Canonical copyThis page. Source: docs/docs/security-whitepaper.mdx
Security contactsecurity@aliasvault.com, see SECURITY.md

Revision history​

VersionDateChanges
0.5 (draft)2026-10-18Converted to whitepaper format: threat model, known limitations and appendices added; updated for the 0.31 vault format.
0.42026-09-30Raised Argon2id defaults.
0.32025-11-18Login with Mobile; clarified zero-knowledge scope.
0.22025-10-28Passkeys.
0.12024-11-08First security architecture page and diagram.