Open-Source Wikis

/

Bitwarden Server

/

Features

/

Key management & rotation

bitwarden/server

Key management & rotation

Active contributors: key management team.

Purpose

The Key Management feature owns the user encryption key lifecycle: how it is derived, stored, wrapped, rotated, and recovered. The actual cryptography is split between client and (in newer code) the Bitwarden Rust SDK; the server's job is to enforce that key changes are atomic and that every dependent piece of data is re-wrapped at the same time.

Where the code lives

src/Core/KeyManagement/
├── Authorization/
├── Commands/
├── Constants.cs
├── Entities/
├── Enums/
├── Kdf/                 # PBKDF2 / Argon2id parameters and migration helpers
├── KeyManagementServiceCollectionExtensions.cs
├── Models/
├── Queries/
├── Repositories/
├── Sends/               # Send-key migration helpers
├── UserKey/             # User-key rotation commands
└── Utilities/

src/Api/KeyManagement/
├── Validators/          # IRotationValidator<T> — one per dependent data type
└── Controllers/

util/RustSdk/             # The Rust SDK consumed by parts of the cipher domain

Key abstractions

Type Path Description
User columns src/Core/Entities/User.cs Key (master-password-sealed user key), PublicKey, PrivateKey (user-key-wrapped), SignedPublicKey, Kdf, KdfIterations, KdfMemory, KdfParallelism.
IUserKeyCommand family src/Core/KeyManagement/UserKey/Commands/ Atomic key rotation; wraps every dependent record together.
IRotationValidator<TIn,TOut> src/Api/KeyManagement/Validators/ Each implementation validates that a particular set of records (ciphers, folders, sends, emergency access, organization-user resets, WebAuthn keys, device keys) has been re-wrapped under the new user key. The set is exhaustive: rotation cannot proceed unless every validator passes.
IKdfMigrator src/Core/KeyManagement/Kdf/ Migrates a user from PBKDF2 to Argon2id (or up-iterates PBKDF2).
IUserService.RotateUserKey src/Core/Services/Implementations/UserService.cs The orchestration point — loops over all rotation validators and persists.

How it works

sequenceDiagram
    participant Client
    participant Api
    participant Validators as IRotationValidator implementations
    participant DB

    Client->>Client: derive new master key, new user key
    Client->>Client: re-wrap every cipher, folder, send, etc.
    Client->>Api: POST /accounts/key (new payload)
    Api->>Validators: for each (Ciphers, Folders, Sends, EmergencyAccess, OrgUsers, WebAuthn, Devices)
    Validators->>DB: ensure exact 1-to-1 mapping<br/>between current rows and submitted re-wrapped versions
    Api->>DB: persist wrapped Key, PrivateKey, etc. + each dependent row
    Api-->>Client: 200 ok

The strictness is intentional: if rotation persisted only the new user key but missed re-wrapping a single cipher, that cipher would become unreadable. IRotationValidator ensures every dependent row is accounted for before any write happens.

KDF migrations

The default for new users since 2023 has been Argon2id (3 iterations, 64 MB memory, 4 parallelism). PBKDF2 (600k iterations) remains supported for legacy users. Migrations happen at password-change time — the client computes the new master-password hash with the new KDF parameters and submits both the old and new wrapped user keys.

Master-password reset (Org-level)

If an organization enables the Account Recovery policy (PolicyType.ResetPassword), administrators can reset member passwords. Each member's OrganizationUser.ResetPasswordKey holds their user key wrapped under the org public key; admins decrypt with the org private key, derive a new wrapped user key, and update the user.

SDK port

util/RustSdk/ exists so that encryption and decryption logic can be shared between the Bitwarden client SDK (which talks to all Bitwarden front-ends) and the server. The cipher domain has been incrementally migrated to call SDK functions for the parts of cipher creation that benefit (PR #7457 "PM-19944 Remove feature flag pm-19941-migrate-cipher-domain-to-sdk", 2026-04-13). The plan is to extend SDK use into other domains over time.

Integration points

  • Auth — master-password change and KDF migration are entry points to key rotation.
  • Vault, Tools, AdminConsole, Auth — every dependent record lives here; rotation validators ensure they all migrate together.
  • Emergency Access — the grantee's wrapped user key has to be updated whenever the grantor rotates.
  • Devices — TDE devices hold device-specific wrapped user keys that must also be rotated.

Entry points for modification

  • Add a new entity holding a wrapped key → write an IRotationValidator<TIn,TOut>, register in services.AddUserKeyCommands, ensure the rotation API accepts the new request shape.
  • Update default KDF parameters → edit KdfMigratorOptions (src/Core/KeyManagement/Kdf/).
  • Add a new key-management endpoint → src/Api/KeyManagement/Controllers/ and a domain command in src/Core/KeyManagement/Commands/.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Key management & rotation – Bitwarden Server wiki | Factory