Overview
The KeyService manages all cryptographic keys in Bitwarden, including user keys, organization keys, provider keys, and key pairs. It handles key generation, derivation, storage, and rotation.
Location
Interface
User Key Management
userKey$()
Returns an observable stream of the user’s encryption key.
Parameters:
Returns: Observable<UserKey | null> - Stream of user keys (null if user is locked/logged out)
Example:
getUserKey()
Retrieves the user’s encryption key.
Parameters:
userId - Optional user ID
Returns: Promise<UserKey | null> - The user key or null
Deprecated. Use userKey$() with a required UserId instead.
setUserKey()
Sets the user key and stores any additional versions (auto, biometrics, pin).
Parameters:
key - The user key to set
userId - The user ID
Throws: Error when key or userId is null. Lock the account to clear a key.
hasUserKey()
Checks if a user key is available in memory.
Parameters:
Returns: Promise<boolean> - True if user key is available
clearStoredUserKey()
Clears the stored user key from storage.
Parameters:
Throws: Error when userId is null or undefined
Key Generation
makeUserKey()
Generates a new user key and encrypts it with the master key.
Parameters:
masterKey - The user’s master key
Returns: Promise<[UserKey, EncString]> - Tuple of new user key and encrypted version
Throws: Error when master key is null or undefined
Deprecated. Interacting with the master key directly is prohibited. For new features, use SDK methods for user cryptography initialization or contact the KM team.
makeMasterKey()
Derives a master key from password using KDF.
Parameters:
password - The user’s master password
email - The user’s email address
kdfConfig - Key derivation function configuration
Returns: Promise<MasterKey> - Derived master key
Deprecated. Interacting with the master key directly is prohibited.
makeCipherKey()
Generates a new cipher encryption key.
Returns: Promise<CipherKey> - A new cipher key
Example:
makeDataEncKey()
Generates a new data encryption key and wraps it with the provided key.
Parameters:
key - User key or organization key to wrap with
Returns: Promise<[SymmetricCryptoKey, EncString]> - New key and wrapped version
Deprecated. Do not use this for new code / new cryptographic designs.
makeSendKey()
Creates a Send encryption key from key material.
Parameters:
keyMaterial - Key material to derive from
Returns: Promise<SymmetricCryptoKey> - Send key
Asymmetric Key Operations
makeKeyPair()
Generates a new RSA key pair.
Parameters:
key - Symmetric key to wrap the private key with
Returns: Promise<[string, EncString]> - Tuple of [publicKey, wrappedPrivateKey]
Throws: Error if the provided key is null
Deprecated. New use-cases should be done in the SDK. Contact the Key Management team.
makeOrgKey()
Creates a new organization key encrypted with the user’s public key.
Parameters:
userId - User ID for public key lookup
Returns: Promise<[EncString, T]> - Encrypted org/provider key and decrypted key
Throws:
Error when userId is null or undefined
Error when no public key is found for the user
userPrivateKey$()
Returns an observable of the user’s decrypted private key.
Parameters:
Returns: Observable<UserPrivateKey | null> - Stream of private keys
userPublicKey$()
Returns an observable of the user’s public key.
Parameters:
Returns: Observable<Uint8Array | null> - Stream of public keys
userEncryptionKeyPair$()
Returns an observable of the user’s key pair (guaranteed to be consistent).
Parameters:
Returns: Observable<{privateKey, publicKey} | null> - Key pair or null
getFingerprint()
Generates a fingerprint phrase for a public key.
Parameters:
fingerprintMaterial - Material to include in fingerprint
publicKey - The public key
Returns: Promise<string[]> - Array of fingerprint words
Throws: Error when publicKey is null or undefined
Master Key Operations
getOrDeriveMasterKey()
Retrieves or derives the master key from a password.
Parameters:
password - The master password
userId - The user ID
Returns: Promise<MasterKey> - The master key
Throws:
Error when userId is null/undefined
Error when email or KDF config cannot be found
Deprecated. Use a high-level function from MasterPasswordService instead.
encryptUserKeyWithMasterKey()
Encrypts the user key with the master key.
Parameters:
masterKey - The master key
userKey - The user key to encrypt
Returns: Promise<[UserKey, EncString]> - User key and encrypted version
Throws: Error when userKey or masterKey is null/undefined
Deprecated. Use a high-level function from MasterPasswordService instead.
hashMasterKey()
Creates a master password hash for authentication.
Parameters:
password - The master password
key - The master key
hashPurpose - Hash purpose (defaults to HashPurpose.ServerAuthorization)
Returns: Promise<string> - Password hash
Hash Purposes:
Deprecated. Use a high-level function from MasterPasswordService instead.
Organization Key Management
setOrgKeys()
Stores encrypted organization keys.
Parameters:
orgs - Organization data
providerOrgs - Provider organization data
userId - The user ID
getOrgKey()
Retrieves an organization’s symmetric key.
Parameters:
orgId - The organization ID
Returns: Promise<OrgKey | null> - The organization key
Throws: Error when not active user
Deprecated. Use the observable userOrgKeys$ and map to the desired OrgKey instead.
orgKeys$()
Returns an observable of all organization keys for a user.
Parameters:
Returns: Observable<Record<OrganizationId, OrgKey> | null> - Map of org IDs to keys
Throws: Error if an invalid user ID is passed
Provider Key Management
setProviderKeys()
Stores provider keys for a user.
Parameters:
providers - Provider organization data
userId - The user ID
providerKeys$()
Returns an observable of provider keys.
Parameters:
Returns: Observable<Record<ProviderId, ProviderKey> | null> - Map of provider IDs to keys
Throws: Error if an invalid user ID is passed
Cipher Decryption Keys
cipherDecryptionKeys$()
Returns all keys needed for decrypting ciphers.
Parameters:
userId - The user ID
legacySupport - Support legacy key format (default: false)
Returns: Observable<CipherDecryptionKeys | null> - Decryption keys
Types:
Throws: Error if an invalid user ID is passed
Account Initialization
initAccount()
Initializes all necessary crypto keys for a new account.
Parameters:
Returns: Promise<{userKey, publicKey, privateKey}> - Newly created keys
Throws:
Error if userId is null or undefined
Error if user already has a user key
Deprecated. New cryptography initialization should be done in the SDK. See PM-21771.
Key Validation
validateUserKey()
Validates that a user key is correct for a given user.
Parameters:
key - The key to validate
userId - The user ID
Returns: Promise<boolean> - True if key is valid
Cleanup
clearKeys()
Clears all of the user’s keys from storage.
Parameters:
Throws: Error when userId is null or undefined
Key Types
All key types are branded types built on top of SymmetricCryptoKey or Uint8Array:
Location: libs/common/src/types/key.ts
KDF Configuration
Key Derivation Function (KDF) configurations control how master keys are derived from passwords.
KdfConfig
Union type for KDF configurations:
PBKDF2KdfConfig
PBKDF2-SHA256 configuration:
Example:
Argon2KdfConfig
Argon2id configuration:
Example:
KdfType
Location: libs/key-management/src/models/kdf-config.ts
Usage Examples
Generating and Setting User Key
Accessing User Keys
Deriving Master Key
Creating Organization Key
Getting Cipher Decryption Keys
Generating Fingerprint
Security Considerations
-
Master Key Deprecation: Direct interaction with master keys is deprecated. Use
MasterPasswordService for high-level operations.
-
Key Storage: User keys should be cleared from memory when the user locks their vault.
-
KDF Configuration: Use appropriate KDF parameters:
- PBKDF2: Minimum 600,000 iterations
- Argon2id: Minimum 2 iterations, 16 MB memory, 1 parallelism
-
Key Validation: Always validate keys before use with
validateUserKey().
-
Observable Cleanup: Subscribe to key observables carefully to avoid memory leaks.
-
SDK Migration: New cryptographic features should use SDK methods instead of these low-level functions.
-
Error Handling: Many methods throw errors. Always wrap in try-catch blocks.
-
User Context: Most operations require a
UserId. Never use keys from one user for another user’s data.