KeyVault
Class: KeyVault
Defined in: packages/sealed-client/src/vault.ts:152
Client side of sealed fields: holds the user keyring on this device and opens sealed values.
The keyring (every private key of the user, by kid) is encrypted with a random keyring key; the keyring key is wrapped by the device KEK in the local storage and by the password / recovery code escrows on the server. Private keys live in memory, non-extractable, only while unlocked.
Public key pinning: the fingerprint of the active public key is pinned in the storage (webda-sealed:pin:<userId>).
A served active key with another fingerprint is refused with a KeyringPinError, unless this device rotated it, or
verified the rotation: a keyring opened with the keyring key (refreshed at unlock, or through an escrow) that still
holds the pinned private key. Besides its own rotation, an explicit KeyVault.reset is the only pin change a
device makes by itself; KeyVault.forgetPin lets the user trust a new key on first use again.
Constructors
Constructor
new KeyVault(
options):KeyVault
Defined in: packages/sealed-client/src/vault.ts:160
Parameters
options
user, server operations and local storage
Returns
KeyVault
Properties
options
protectedoptions:KeyVaultOptions
Defined in: packages/sealed-client/src/vault.ts:160
user, server operations and local storage
Accessors
isUnlocked
Get Signature
get isUnlocked():
boolean
Defined in: packages/sealed-client/src/vault.ts:163
Returns
boolean
true while the private keys are in memory
Methods
changePassword()
changePassword(
newPassword,opts?):Promise<void>
Defined in: packages/sealed-client/src/vault.ts:395
Re-wrap the keyring key under a new password and replace the password escrow: directly while unlocked, otherwise
through the password escrow opened with the old password (a throttled getEscrow, checked against the pin).
The password escrow must follow the login password: the host changes both together (this call right after, or before, the login password change), otherwise the next device has to be added with the old password.
While unlocked, the change is refused with a KeyringPinError when the keyring changed on another device since
the unlock (its keyring key may have been replaced): unlock again first.
Parameters
newPassword
string
new password
opts?
options
oldPassword?
string
current password, needed while locked
Returns
Promise<void>
enroll()
enroll(
input):Promise<{recoveryCode?:string; }>
Defined in: packages/sealed-client/src/vault.ts:189
First device: generate the user key pair and keyring, escrow the keyring key, keep it on this device and pin the public key. The device KEK is derived before anything is sent, so a failing KEK leaves nothing on the server; once the server accepted the keys, the device blob and the pin are stored before the device registration, which is retried by the next unlock when it fails.
Parameters
input
enrollment
device
device KEK
deviceName
string
name registered for this device
password?
string
password escrow (the login password, its KEK is derived locally with its own salt)
recovery?
boolean
also create a recovery code escrow
Returns
Promise<{ recoveryCode?: string; }>
the recovery code, to show once
forgetPin()
forgetPin():
Promise<void>
Defined in: packages/sealed-client/src/vault.ts:474
Forget the public key pinned on this device and lock: the next KeyVault.unlockWithEscrow trusts the served key on first use, as on a new device. For the user to call explicitly after a KeyVault.reset done on another device, ideally once the new fingerprint was compared out of band
Returns
Promise<void>
lock()
lock():
void
Defined in: packages/sealed-client/src/vault.ts:588
Drop the keys from memory
Returns
void
open()
open<
T>(env,ctx):Promise<T>
Defined in: packages/sealed-client/src/vault.ts:352
Open a sealed value with the private key of its kid (retired keys stay readable). The private keys all come
from a keyring authenticated against the pinned active key (or a verified rotation of it), each checked against
its served public key
Type Parameters
T
T = unknown
Parameters
env
sealed envelope
ctx
model type, uuid and field it is stored in (AAD)
Returns
Promise<T>
the value
removeRecoveryCode()
removeRecoveryCode():
Promise<void>
Defined in: packages/sealed-client/src/vault.ts:429
Remove the recovery code escrow (User.Keys.RemoveEscrow). The server refuses to remove the last escrow while no
device is registered (409, surfaced as the api error)
Returns
Promise<void>
reset()
reset(
input):Promise<{recoveryCode?:string; }>
Defined in: packages/sealed-client/src/vault.ts:449
Keys lost (no device left, password and recovery code forgotten): start over with a new key pair and a new keyring
key, through User.Keys.Rotate (fresh authentication required, the vault does not need to be unlocked).
The new keyring holds the new private key only: values sealed to the older keys stay unreadable, new values open.
The requested escrows replace the old ones, this device keeps the new keyring key and is registered (kept when
already registered), and the pin moves to the new key: an explicit reset by the user is, with its own rotation, the
only pin change a device makes by itself. The other devices are cut off (their unlock fails with a
KeyringPinError); they are added again with the new escrow after KeyVault.forgetPin.
Parameters
input
EscrowRequest & object
reset
Returns
Promise<{ recoveryCode?: string; }>
the recovery code when one was requested, to show once
rotate()
rotate(
options?):Promise<{recoveryCode?:string; }>
Defined in: packages/sealed-client/src/vault.ts:491
Rotate: a new active key pair added to the keyring, the keyring re-encrypted for it, and the pin moved to it. Values sealed to older keys stay readable.
By default the keyring key is kept, so the escrows stay valid: a device that kept its blob (lost or revoked) can
still open the keyring. With newKeyringKey, a fresh keyring key encrypts the keyring, the requested escrows are
rebuilt and replace the old ones, and this device re-wraps its blob with its KEK: the answer to a lost or revoked
device.
Parameters
options?
rotation options
newKeyringKey?
EscrowRequest & object
replace the keyring key: the device KEK of this device and the escrows to create
Returns
Promise<{ recoveryCode?: string; }>
the new recovery code when one was requested, to show once
seal()
seal(
value,ctx,recipient?):Promise<SealedEnvelope>
Defined in: packages/sealed-client/src/vault.ts:368
Seal a value to the user pinned public key (works while locked)
Parameters
value
unknown
JSON-encodable value
ctx
model type, uuid and field it will be stored in (AAD)
recipient?
PublicKeyEntry
public key to seal to, refused unless it is the pinned key (default: the active key)
Returns
Promise<SealedEnvelope>
the envelope
setRecoveryCode()
setRecoveryCode():
Promise<string>
Defined in: packages/sealed-client/src/vault.ts:414
Create or replace the recovery code escrow; refused with a KeyringPinError when the keyring changed on another
device since the unlock (unlock again first)
Returns
Promise<string>
the recovery code, to show once
unlock()
unlock(
device):Promise<void>
Defined in: packages/sealed-client/src/vault.ts:222
Unlock this device with its KEK; the server is only asked for the public keys, checked against the pin, and the devices: a device revoked on the server deletes its local blob (DeviceRevokedError).
A stale local keyring (rotated on another device) is refreshed with User.Keys.GetKeyring: the served keyring
must open with the keyring key of this device and still hold the pinned private key, otherwise the unlock fails with
a KeyringPinError (the keyring key was replaced: unlock with an escrow).
Parameters
device
device KEK
Returns
Promise<void>
unlockWithEscrow()
unlockWithEscrow(
secret,register):Promise<void>
Defined in: packages/sealed-client/src/vault.ts:301
Open the keyring with an escrow and keep it on this device (adds a device, or verifies a rotation done on another device: the new keyring must hold the pinned private key)
Parameters
secret
password or recovery code
register
device KEK and name
device
device KEK
deviceName
string
name registered for this device
Returns
Promise<void>