Skip to content

@btravstack/keys


@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 ​

Constructors ​

Constructor ​
ts
new EnvelopeKeys(): EnvelopeKeys;

Defined in: packages/di/dist/index.d.mts:15

Returns ​

EnvelopeKeys

Inherited from ​

Port("EnvelopeKeys")<EnvelopeKeysService>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
[ID]readonly"EnvelopeKeys"Port("EnvelopeKeys").[ID]packages/di/dist/index.d.mts:11
[SERVICE]readonlyEnvelopeKeysServicePort("EnvelopeKeys").[SERVICE]packages/di/dist/index.d.mts:12
portIdstatic readonly"EnvelopeKeys"Port("EnvelopeKeys").portIdpackages/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 ​
ts
new InvalidKeyPurpose(args): InvalidKeyPurpose;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsobject & object
Returns ​

InvalidKeyPurpose

Inherited from ​

TaggedError("InvalidKeyPurpose")<{ readonly namespace: string; readonly purpose: string; readonly version: number; }>.constructor

Properties ​

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
_tagreadonly"InvalidKeyPurpose"undefined-TaggedError("InvalidKeyPurpose")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownundefined-TaggedError("InvalidKeyPurpose").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstring"the key purpose is not a valid HKDF info"TaggedError("InvalidKeyPurpose").message-packages/keys/src/derive.ts:29
namepublicstringundefined-TaggedError("InvalidKeyPurpose").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
namespacereadonlystringundefined-TaggedError("InvalidKeyPurpose").namespacepackages/keys/src/derive.ts:25
purposereadonlystringundefined-TaggedError("InvalidKeyPurpose").purposepackages/keys/src/derive.ts:26
stack?publicstringundefined-TaggedError("InvalidKeyPurpose").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076
versionreadonlynumberundefined-TaggedError("InvalidKeyPurpose").versionpackages/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 ​
ts
new KeyErased(args): KeyErased;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsobject & object
Returns ​

KeyErased

Inherited from ​

TaggedError("KeyErased")<{ readonly owner: string; readonly keyId: string; readonly reason: "disabled" | "pending_deletion" | "not_found" | "refused"; }>.constructor

Properties ​

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
_tagreadonly"KeyErased"undefined-TaggedError("KeyErased")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
cause?publicunknownundefined-TaggedError("KeyErased").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
keyIdreadonlystringundefined-TaggedError("KeyErased").keyIdpackages/keys/src/keys.ts:31
messagepublicstring"the key generation is erased"TaggedError("KeyErased").message-packages/keys/src/keys.ts:34
namepublicstringundefined-TaggedError("KeyErased").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
ownerreadonlystringundefined-TaggedError("KeyErased").ownerpackages/keys/src/keys.ts:30
reasonreadonly"disabled" | "pending_deletion" | "not_found" | "refused"undefined-TaggedError("KeyErased").reasonpackages/keys/src/keys.ts:32
stack?publicstringundefined-TaggedError("KeyErased").stacknode_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 ​
ts
new KeysUnavailable(args): KeysUnavailable;

Defined in: node_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2386

Parameters ​
ParameterType
argsobject & object
Returns ​

KeysUnavailable

Inherited from ​

TaggedError("KeysUnavailable")<{ readonly operation: "unwrap" | "provision" | "erase"; readonly owner: string; readonly cause: unknown; }>.constructor

Properties ​

PropertyModifierTypeDefault valueOverridesInherited fromDefined in
_tagreadonly"KeysUnavailable"undefined-TaggedError("KeysUnavailable")._tagnode_modules/.pnpm/unthrown@5.12.1/node_modules/unthrown/dist/index.d.mts:2363
causepublicunknownundefined-InvalidKeyPurpose.causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstring"the key-management service could not be asked"TaggedError("KeysUnavailable").message-packages/keys/src/keys.ts:48
namepublicstringundefined-TaggedError("KeysUnavailable").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
operationreadonly"unwrap" | "provision" | "erase"undefined-TaggedError("KeysUnavailable").operationpackages/keys/src/keys.ts:44
ownerreadonlystringundefined-TaggedError("KeysUnavailable").ownerpackages/keys/src/keys.ts:45
stack?publicstringundefined-TaggedError("KeysUnavailable").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Type Aliases ​

DerivedKey ​

ts
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 ​

PropertyModifierTypeDefined in
algorithmreadonlywebcrypto.AesDerivedKeyParams | webcrypto.HmacImportParamspackages/keys/src/derive.ts:19
usagesreadonlyreadonly webcrypto.KeyUsage[]packages/keys/src/derive.ts:20

EnvelopeKeysService ​

ts
type EnvelopeKeysService = object;

Defined in: packages/keys/src/keys.ts:51

Properties ​

PropertyModifierTypeDescriptionDefined in
erasereadonly(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
provisionreadonly(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
rootKeyreadonly(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 ​

ts
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 ​

PropertyModifierTypeDefined in
keyIdreadonlystringpackages/keys/src/keys.ts:18
ownerreadonlystringpackages/keys/src/keys.ts:17
wrappedreadonlyUint8Arraypackages/keys/src/keys.ts:19

KeyPurpose ​

ts
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 ​

PropertyModifierTypeDefined in
namespacereadonlystringpackages/keys/src/derive.ts:12
purposereadonlystringpackages/keys/src/derive.ts:13
versionreadonlynumberpackages/keys/src/derive.ts:14

Functions ​

deriveKey() ​

ts
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>.

ts
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 ​

ParameterType
rootCryptoKey
purposeKeyPurpose
derivedDerivedKey

Returns ​

AsyncResult<CryptoKey, InvalidKeyPurpose>

Released under the MIT License.