@btravstack/keys / index
index
Classes
EnvelopeKeys
Defined in: packages/keys/src/keys.ts:83
The port an application depends on for per-owner envelope keys. kmsKeys() from @btravstack/keys/kms provides it over AWS KMS.
Extends
PortInstance<"EnvelopeKeys",EnvelopeKeysService>
Constructors
Constructor
new EnvelopeKeys(): EnvelopeKeys;Defined in: packages/di/dist/index.d.mts:15
Returns
Inherited from
Port("EnvelopeKeys")<EnvelopeKeysService>.constructor
Properties
| Property | Modifier | Type | Inherited from | Defined in |
|---|---|---|---|---|
[ID] | readonly | "EnvelopeKeys" | Port("EnvelopeKeys").[ID] | packages/di/dist/index.d.mts:11 |
[SERVICE] | readonly | EnvelopeKeysService | Port("EnvelopeKeys").[SERVICE] | packages/di/dist/index.d.mts:12 |
portId | static readonly | "EnvelopeKeys" | Port("EnvelopeKeys").portId | packages/di/dist/index.d.mts:16 |
InvalidKeyPurpose
Defined in: packages/keys/src/derive.ts:24
A purpose whose info would be ambiguous: a segment outside the alphabet, or a version that is not a positive integer.
Extends
TaggedErrorInstance<"InvalidKeyPurpose", {namespace:string;purpose:string;version:number; }>
Constructors
Constructor
new InvalidKeyPurpose(args): InvalidKeyPurpose;Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("InvalidKeyPurpose")<{ readonly namespace: string; readonly purpose: string; readonly version: number; }>.constructor
Properties
| Property | Modifier | Type | Default value | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|
_tag | readonly | "InvalidKeyPurpose" | undefined | - | TaggedError("InvalidKeyPurpose")._tag | node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363 |
cause? | public | unknown | undefined | - | TaggedError("InvalidKeyPurpose").cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
message | public | string | "the key purpose is not a valid HKDF info" | TaggedError("InvalidKeyPurpose").message | - | packages/keys/src/derive.ts:29 |
name | public | string | undefined | - | TaggedError("InvalidKeyPurpose").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
namespace | readonly | string | undefined | - | TaggedError("InvalidKeyPurpose").namespace | packages/keys/src/derive.ts:25 |
purpose | readonly | string | undefined | - | TaggedError("InvalidKeyPurpose").purpose | packages/keys/src/derive.ts:26 |
stack? | public | string | undefined | - | TaggedError("InvalidKeyPurpose").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
version | readonly | number | undefined | - | TaggedError("InvalidKeyPurpose").version | packages/keys/src/derive.ts:27 |
KeyErased
Defined in: packages/keys/src/keys.ts:29
The generation can no longer be unwrapped, and never will be again: the owner's key is disabled (disabled), scheduled for deletion (pending_deletion), gone (not_found), or refused this ciphertext under this owner and key id (refused). An answer, not an outage: whatever the generation protected is erased.
Extends
TaggedErrorInstance<"KeyErased", {keyId:string;owner:string;reason:"disabled"|"pending_deletion"|"not_found"|"refused"; }>
Constructors
Constructor
new KeyErased(args): KeyErased;Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("KeyErased")<{ readonly owner: string; readonly keyId: string; readonly reason: "disabled" | "pending_deletion" | "not_found" | "refused"; }>.constructor
Properties
| Property | Modifier | Type | Default value | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|
_tag | readonly | "KeyErased" | undefined | - | TaggedError("KeyErased")._tag | node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363 |
cause? | public | unknown | undefined | - | TaggedError("KeyErased").cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
keyId | readonly | string | undefined | - | TaggedError("KeyErased").keyId | packages/keys/src/keys.ts:31 |
message | public | string | "the key generation is erased" | TaggedError("KeyErased").message | - | packages/keys/src/keys.ts:34 |
name | public | string | undefined | - | TaggedError("KeyErased").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
owner | readonly | string | undefined | - | TaggedError("KeyErased").owner | packages/keys/src/keys.ts:30 |
reason | readonly | "disabled" | "pending_deletion" | "not_found" | "refused" | undefined | - | TaggedError("KeyErased").reason | packages/keys/src/keys.ts:32 |
stack? | public | string | undefined | - | TaggedError("KeyErased").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
KeysUnavailable
Defined in: packages/keys/src/keys.ts:43
The key-management service could not be asked: throttling, the network, a credential or permission it refused, a server error. Transient or a deployment mistake, never an erasure, so a later call asks again: a failure is never cached.
Extends
TaggedErrorInstance<"KeysUnavailable", {cause:unknown;operation:"unwrap"|"provision"|"erase";owner:string; }>
Constructors
Constructor
new KeysUnavailable(args): KeysUnavailable;Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386
Parameters
| Parameter | Type |
|---|---|
args | object & object |
Returns
Inherited from
TaggedError("KeysUnavailable")<{ readonly operation: "unwrap" | "provision" | "erase"; readonly owner: string; readonly cause: unknown; }>.constructor
Properties
| Property | Modifier | Type | Default value | Overrides | Inherited from | Defined in |
|---|---|---|---|---|---|---|
_tag | readonly | "KeysUnavailable" | undefined | - | TaggedError("KeysUnavailable")._tag | node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363 |
cause | public | unknown | undefined | - | InvalidKeyPurpose.cause | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24 |
message | public | string | "the key-management service could not be asked" | TaggedError("KeysUnavailable").message | - | packages/keys/src/keys.ts:48 |
name | public | string | undefined | - | TaggedError("KeysUnavailable").name | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074 |
operation | readonly | "unwrap" | "provision" | "erase" | undefined | - | TaggedError("KeysUnavailable").operation | packages/keys/src/keys.ts:44 |
owner | readonly | string | undefined | - | TaggedError("KeysUnavailable").owner | packages/keys/src/keys.ts:45 |
stack? | public | string | undefined | - | TaggedError("KeysUnavailable").stack | node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076 |
Type Aliases
DerivedKey
type DerivedKey = object;Defined in: packages/keys/src/derive.ts:18
What the derived key is, as WebCrypto's deriveKey takes it. It is never extractable.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
algorithm | readonly | webcrypto.AesDerivedKeyParams | webcrypto.HmacImportParams | packages/keys/src/derive.ts:19 |
usages | readonly | readonly webcrypto.KeyUsage[] | packages/keys/src/derive.ts:20 |
EnvelopeKeysService
type EnvelopeKeysService = object;Defined in: packages/keys/src/keys.ts:51
Properties
| Property | Modifier | Type | Description | Defined in |
|---|---|---|---|---|
erase | readonly | (owner) => AsyncResult<void, KeysUnavailable> | Every generation of the owner, erased at once: the owner's key is scheduled for deletion, so from then on each generation answers KeyErased. Erasing an owner already erased answers Ok. | packages/keys/src/keys.ts:76 |
provision | readonly | (owner, keyId) => AsyncResult<KeyGeneration, KeyErased | KeysUnavailable> | A new generation under the owner's key, for the application to keep. Rotation is provisioning another key id; the old generations stay readable until the owner is erased. | packages/keys/src/keys.ts:66 |
rootKey | readonly | (generation) => AsyncResult<webcrypto.CryptoKey, KeyErased | KeysUnavailable> | The generation's root key, unwrapped in memory: a non-extractable HKDF key, to derive a key per purpose from with deriveKey. Kept for the cache's TTL; callers asking while it is being unwrapped share one request. | packages/keys/src/keys.ts:57 |
KeyGeneration
type KeyGeneration = object;Defined in: packages/keys/src/keys.ts:16
One generation of an owner's root key, as it is kept: wrapped by the owner's key-management key, under an encryption context that binds owner and keyId.
wrapped is not secret — only the key-management service can unwrap it, and only for this owner and this key id — so it may live wherever the application keeps configuration: a mounted Secret, a file, an object store, a database row.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
keyId | readonly | string | packages/keys/src/keys.ts:18 |
owner | readonly | string | packages/keys/src/keys.ts:17 |
wrapped | readonly | Uint8Array | packages/keys/src/keys.ts:19 |
KeyPurpose
type KeyPurpose = object;Defined in: packages/keys/src/derive.ts:11
What a derived key is for, spelled into HKDF's info as <namespace>/<purpose>/v<version>. Each segment is ASCII letters, digits, ., _ or -, so no two purposes spell the same info; version is a positive integer, raised to retire a derived key without a new root.
Properties
| Property | Modifier | Type | Defined in |
|---|---|---|---|
namespace | readonly | string | packages/keys/src/derive.ts:12 |
purpose | readonly | string | packages/keys/src/derive.ts:13 |
version | readonly | number | packages/keys/src/derive.ts:14 |
Functions
deriveKey()
function deriveKey(
root,
purpose,
derived
): AsyncResult<CryptoKey, InvalidKeyPurpose>;Defined in: packages/keys/src/derive.ts:51
A key for one purpose, derived from a root key with HKDF-SHA-256, an empty salt and info = <namespace>/<purpose>/v<version>.
keys.rootKey(generation).flatMap((root) =>
deriveKey(root, { namespace: "payloads", purpose: "seal", version: 1 }, {
algorithm: { name: "AES-GCM", length: 256 },
usages: ["encrypt", "decrypt"],
}),
);Every purpose gets its own key, and so its own nonce budget: two uses of random 96-bit AES-GCM nonces never draw from one key. The salt is empty because the root is already uniformly random (RFC 5869, section 3.1).
Parameters
| Parameter | Type |
|---|---|
root | CryptoKey |
purpose | KeyPurpose |
derived | DerivedKey |
Returns
AsyncResult<CryptoKey, InvalidKeyPurpose>