public final class VaultOptions
- Object
- VaultOptions
What a caller insists on when opening or enrolling a vault.
The reason this exists rather than a set of arguments: the important option is the one that
says fail instead of doing something weaker. A vault asked for encrypted, non-extractable
storage on a platform that can only offer a plaintext string has exactly two honest
behaviours, and silently taking the second is how an application ends up believing it is
protecting something it is not. Listing a protection in require(Protection) turns that into
a VaultError.POLICY_NOT_MET naming the protection that was missing.
Nothing here is required. A new VaultOptions() carries the defaults an application that has
not thought about it should get: today’s KDF profile, session-only access, no auto lock, and
no required protections – which means the vault reports what it managed rather than
refusing.
Constructors
public VaultOptions() |
Methods
Inherited methods
Constructor details
VaultOptions
public VaultOptions()Method details
require
public VaultOptions require(Protection protection)getRequired
public Protection[] getRequired()kdf
public VaultOptions kdf(KdfProfile profile)KdfProfile.current(), and lowering it weakens every password wrap the vault writes.getKdf
public KdfProfile getKdf()policy
public VaultOptions policy(UnlockPolicy newPolicy)UnlockPolicy.getPolicy
public UnlockPolicy getPolicy()autoLockAfter
public VaultOptions autoLockAfter(long millis)Locks the vault after this many milliseconds without a vault operation. Zero, the default, never auto locks.
Enforced when the vault is next used rather than by a timer, so a vault that is idle stays
nominally unlocked until something asks – at which point it locks and the call fails with
VaultError.LOCKED. A timer would be tidier and would also keep a reference alive and
wake a sleeping device; the check-on-use form cannot be late in any way a caller can
observe, because nothing observes the vault except through a call.
getAutoLockMillis
public long getAutoLockMillis()requireOpaqueKeysOnly
public VaultOptions requireOpaqueKeysOnly()Refuses any operation that would produce raw key bytes, at the cost of the encrypted database.
The one place this package hands out key material is Vault.databaseKey(String), because
SQLCipher – on the device and in the browser’s WASM build alike – takes a key as bytes
and there is no arrangement of opaque handles that changes that. A caller that cannot
accept the exposure sets this, and that call then fails with
VaultError.POLICY_NOT_MET rather than quietly doing the thing the policy forbade.
The consequence is real and is the point: a vault configured this way cannot key a managed
encrypted database. An application that needs both has to seal its records through
Vault.seal and store the ciphertext in a plain database, which is a different design
rather than a setting.
isOpaqueKeysOnly
public boolean isOpaqueKeysOnly()requireOpaqueKeysOnly().deviceProtection
public VaultOptions deviceProtection(DeviceProtection protection)Supplies the device key store rather than using the port’s.
The port’s is right for almost everything, and this exists for the cases where it is not: a library wrapping a hardware token, an application whose key belongs to a management agent rather than to the device, and a test that needs the remembered-device paths without a platform key store behind them.
Supplying one does not relax any check. A protection required through
require(Protection) is still checked against what this reports, so an implementation
that claims more than it provides fails the same way the port would.
Parameters
protectionDeviceProtection- the device key store, or null to use the port’s
requireDeviceBoundPasskey
public VaultOptions requireDeviceBoundPasskey()Requires that a passkey used for UnlockPolicy.REQUIRE_USER_VERIFICATION cannot leave
this device.
Why this is a choice and not a default
Most passkeys sync. An iCloud Keychain credential reaches every device on the Apple account, and a Google-account one every device signed into it – so the ordinary “remember this device” is closer to “remember this account”. For a note-taking application that is what the user wants: a new laptop unlocks with a face scan and no password. For something holding a second factor it is the opposite of what was asked for.
Requiring this narrows the ceremony to an authenticator built into the machine and
checks the credential’s backup-eligibility flag, which is the part that actually decides.
authenticatorAttachment: "platform" alone does not: an iCloud Keychain passkey is
platform-attached and syncs anyway.
What it costs
Hardware security keys are excluded, and so is every authenticator whose browser will not
report the flag – an unknown answer is treated as “may leave this device” rather than
rounded up. A user whose only authenticator syncs cannot enrol, and enrolment fails with
VaultError.POLICY_NOT_MET rather than quietly keeping a credential that does not meet
the requirement. Offer the weaker policy as a fallback, or do not require this.
isDeviceBoundPasskeyRequired
public boolean isDeviceBoundPasskeyRequired()requireDeviceBoundPasskey().getDeviceProtection
public DeviceProtection getDeviceProtection()deviceProtection, or null for the port’s.