@sebastienrousseau/crypto-kms 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ This project is dual-licensed under either of:
2
+
3
+ * Apache License, Version 2.0 — see LICENSE-APACHE
4
+ * MIT license — see LICENSE-MIT
5
+
6
+ at your option.
7
+
8
+ SPDX-License-Identifier: Apache-2.0 OR MIT
package/README.md ADDED
@@ -0,0 +1,320 @@
1
+ <!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->
2
+
3
+ <p align="center">
4
+ <img src="https://raw.githubusercontent.com/sebastienrousseau/crypto-service/main/assets/crypto-kms-logo.svg" alt="crypto-kms logo" width="360" />
5
+ </p>
6
+
7
+ <h1 align="center">@sebastienrousseau/crypto-kms</h1>
8
+
9
+ <p align="center">
10
+ Unified Key Management Service interface. AWS KMS and an in-memory local provider are implemented; GCP, Azure and Vault are stubs.
11
+ </p>
12
+
13
+ <p align="center">
14
+ <a href="https://github.com/sebastienrousseau/crypto-service/actions"><img src="https://img.shields.io/github/actions/workflow/status/sebastienrousseau/crypto-service/ci.yml?branch=main&style=for-the-badge&logo=github" alt="Build" /></a>
15
+ <a href="https://coveralls.io/github/sebastienrousseau/crypto-service?branch=main"><img src="https://img.shields.io/coveralls/github/sebastienrousseau/crypto-service?branch=main&style=for-the-badge" alt="Coverage" /></a>
16
+ <a href="https://www.npmjs.com/package/@sebastienrousseau/crypto-kms"><img src="https://img.shields.io/npm/v/@sebastienrousseau/crypto-kms.svg?style=for-the-badge&color=f14041&logo=npm" alt="Registry" /></a>
17
+ <a href="https://sebastienrousseau.github.io/crypto-service/"><img src="https://img.shields.io/badge/docs-TypeDoc-blue.svg?style=for-the-badge&labelColor=555555&logo=typescript" alt="Docs" /></a>
18
+ <a href="https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/crypto-service" title="ossf-scorecard"><img src="https://img.shields.io/badge/OpenSSF-Scorecard-blue?style=for-the-badge&logo=openssf" alt="OpenSSF Scorecard" /></a>
19
+ <a href="https://github.com/sebastienrousseau/crypto-service/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg?style=for-the-badge" alt="License: Apache-2.0 OR MIT" /></a>
20
+ <a href="https://github.com/sebastienrousseau/crypto-service/blob/main/docs/POLICIES.md"><img src="https://img.shields.io/badge/Node.js-%3E%3D22-93450a.svg?style=for-the-badge&logo=node.js" alt="Node.js 22 or newer" /></a>
21
+ </p>
22
+
23
+ ---
24
+
25
+ ## Contents
26
+
27
+ **Getting started**
28
+
29
+ - [Install](#install) — installation via pnpm, npm, or yarn
30
+ - [Requirements](#requirements) — runtime floor and environment prerequisites
31
+ - [Quick Start](#quick-start) — minimal working usage sample
32
+
33
+ **The Crypto Service ecosystem**
34
+
35
+ - [The Crypto Service ecosystem](#the-crypto-service-ecosystem) — full 14-package suite overview
36
+
37
+ **Package reference**
38
+
39
+ - [Reference & Usage](#overview) — features, configuration, and capabilities
40
+ - [Examples](#examples) — runnable sample code
41
+
42
+ **Operational**
43
+
44
+ - [Development](#development) — build, lint, format, and test targets
45
+ - [Security](#security) — vulnerability disclosure and cryptographic invariants
46
+ - [Documentation](#documentation) — TypeDoc API docs and ecosystem guides
47
+ - [Stability guarantees](#stability-guarantees) — SemVer axis and release policy
48
+ - [License](#license)
49
+
50
+ ---
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ pnpm add @sebastienrousseau/crypto-kms
56
+ # or
57
+ npm install @sebastienrousseau/crypto-kms
58
+ # or
59
+ yarn add @sebastienrousseau/crypto-kms
60
+ ```
61
+
62
+ <p align="right"><a href="#contents">Back to Top</a></p>
63
+
64
+ ---
65
+
66
+ ## Requirements
67
+
68
+ - **Node.js**: `^22.0.0` or `>=24.0.0` (active and maintenance LTS releases)
69
+ - **Package Manager**: `pnpm >=9` (recommended) or `npm >=10`
70
+ - **TypeScript**: `>=5.0` (when compiling with TypeScript)
71
+
72
+ <p align="right"><a href="#contents">Back to Top</a></p>
73
+
74
+ ---
75
+
76
+ ## Quick Start
77
+
78
+ ```ts
79
+ import { LocalKmsProvider } from "@sebastienrousseau/crypto-kms";
80
+
81
+ const kms = new LocalKmsProvider();
82
+ const key = await kms.createKey("aes-256-gcm", "encrypt");
83
+ const encrypted = await kms.encrypt(
84
+ key.keyId,
85
+ new TextEncoder().encode("secret"),
86
+ );
87
+ const decrypted = await kms.decrypt(key.keyId, encrypted.ciphertext);
88
+ console.log(new TextDecoder().decode(decrypted.plaintext)); // "secret"
89
+ ```
90
+
91
+ <p align="right"><a href="#contents">Back to Top</a></p>
92
+
93
+ ---
94
+
95
+ ## The Crypto Service ecosystem
96
+
97
+ Crypto Service provides a complete cryptography stack across 14 specialized packages:
98
+
99
+ | Package | Role | Description |
100
+ | :-------------------------------------------------------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
101
+ | [`@sebastienrousseau/crypto-api`](../crypto-api) | API Schemas | Shared TypeScript types and utilities for the Crypto Service Suite, defining the canonical API surface. |
102
+ | [`@sebastienrousseau/crypto-cli`](../crypto-cli) | Terminal CLI | An interactive command-line interface for cryptographic operations, supporting both legacy OpenPGP and modern post-quantum algorithms. |
103
+ | [`@sebastienrousseau/crypto-edge`](../crypto-edge) | Edge Runtime | Edge-runtime cryptographic operations using the Web Crypto API, optimized for Cloudflare Workers, Vercel Edge, and Deno. |
104
+ | **[`@sebastienrousseau/crypto-kms`](../crypto-kms)** _(this package)_ | **Cloud KMS** | **Unified KMS interface: AWS KMS and local providers implemented; GCP, Azure and Vault are stubs.** |
105
+ | [`@sebastienrousseau/crypto-lib`](../crypto-lib) | Core Library | A modern cryptographic library for TypeScript, with post-quantum support, zero unsafe dependencies, and 100% test coverage. |
106
+ | [`@sebastienrousseau/crypto-middleware`](../crypto-middleware) | Middleware | Framework-agnostic cryptographic middleware for Express, Fastify, and Koa applications. |
107
+ | [`@sebastienrousseau/crypto-prisma`](../crypto-prisma) | ORM Adapter | Transparent field-level encryption extension for Prisma Client, using XChaCha20-Poly1305. |
108
+ | [`@sebastienrousseau/crypto-react`](../crypto-react) | React Hooks | React hooks and context provider for client-side cryptographic operations with zero boilerplate. |
109
+ | [`@sebastienrousseau/crypto-sdk`](../crypto-sdk) | Client SDK | A zero-dependency, typed HTTP client for the Crypto Service REST API, with full post-quantum support. |
110
+ | [`@sebastienrousseau/crypto-server`](../crypto-server) | HTTP API | A hardened Fastify REST API for cryptographic operations, with rate limiting, OpenAPI schemas, and post-quantum endpoints. |
111
+ | [`@sebastienrousseau/crypto-testing`](../crypto-testing) | Test Support | Deterministic keys, fast mocks, and test fixtures for crypto-lib |
112
+ | [`@sebastienrousseau/crypto-typeorm`](../crypto-typeorm) | ORM Adapter | TypeORM column-level encryption with a single decorator, powered by crypto-lib. |
113
+ | [`@sebastienrousseau/crypto-vue`](../crypto-vue) | Vue Composables | Vue 3 composables for client-side cryptography |
114
+ | [`@sebastienrousseau/crypto-wasm`](../crypto-wasm) | Acceleration | Placeholder for a WebAssembly accelerator; contains no WebAssembly code yet. |
115
+
116
+ <p align="right"><a href="#contents">Back to Top</a></p>
117
+
118
+ ---
119
+
120
+ ## Overview
121
+
122
+ crypto-kms defines a unified `KmsProvider` interface for key
123
+ creation, encryption, decryption, signing, verification, rotation
124
+ and data-key generation. Two providers are implemented: AWS KMS and
125
+ an in-memory local provider. The GCP, Azure and HashiCorp Vault
126
+ providers are stubs: every method rejects with `Not implemented`.
127
+ The PKCS#11 provider is an in-memory software simulation for tests
128
+ (see below); it does not talk to an HSM.
129
+
130
+ <p align="right"><a href="#contents">Back to Top</a></p>
131
+
132
+ ## Providers
133
+
134
+ | Provider | Class | Backend | Status | Peer Dependency |
135
+ | :---------- | :------------------ | :------------------------- | :------------------------------------ | :--------------------- |
136
+ | **AWS** | `AwsKmsProvider` | AWS Key Management Service | Implemented | `@aws-sdk/client-kms` |
137
+ | **GCP** | `GcpKmsProvider` | Google Cloud KMS | Stub (rejects `Not implemented`) | `@google-cloud/kms` |
138
+ | **Azure** | `AzureKmsProvider` | Azure Key Vault | Stub (rejects `Not implemented`) | `@azure/keyvault-keys` |
139
+ | **Vault** | `VaultKmsProvider` | HashiCorp Vault Transit | Stub (rejects `Not implemented`) | None |
140
+ | **Local** | `LocalKmsProvider` | In-memory (crypto-lib) | Implemented | None |
141
+ | **PKCS#11** | `Pkcs11HsmProvider` | None (in-memory) | Software simulation; `simulate: true` | None |
142
+
143
+ `Pkcs11HsmProvider` has no PKCS#11 binding: it never loads a module,
144
+ accepts any PIN, keeps keys in process memory and reports
145
+ `fipsLevel: "none (software simulation)"`. Its constructor throws
146
+ unless you pass `{ simulate: true }`. Use it only in tests.
147
+
148
+ <p align="right"><a href="#contents">Back to Top</a></p>
149
+
150
+ ## API Reference
151
+
152
+ Every provider exposes the `KmsProvider` interface:
153
+
154
+ | Method | Description |
155
+ | :------------------------------------------- | :------------------------------------------- |
156
+ | `listKeys(filters?)` | List all managed keys, with optional filters |
157
+ | `getKey(keyId)` | Retrieve metadata for a specific key |
158
+ | `createKey(algorithm, usage, metadata?)` | Create a new managed key |
159
+ | `enableKey(keyId)` | Enable a disabled key |
160
+ | `disableKey(keyId)` | Disable a key (soft delete) |
161
+ | `scheduleKeyDeletion(keyId, days?)` | Schedule a key for deletion |
162
+ | `encrypt(keyId, plaintext, context?)` | Encrypt plaintext with a managed key |
163
+ | `decrypt(keyId, ciphertext, context?)` | Decrypt ciphertext with a managed key |
164
+ | `sign(keyId, data, algorithm?)` | Sign data with a managed signing key |
165
+ | `verify(keyId, data, signature, algorithm?)` | Verify a signature |
166
+ | `rotateKey(keyId)` | Add a new current key version |
167
+ | `destroyKeyVersion?(keyId, version)` | Destroy a retired version (optional method) |
168
+ | `generateDataKey(keyId, keySpec?)` | Generate a wrapped data encryption key |
169
+
170
+ ### Key rotation and versions
171
+
172
+ `LocalKmsProvider` and `Pkcs11HsmProvider` keep every version of a key.
173
+ `rotateKey` adds a new current version; it does not replace the old
174
+ material. New ciphertext and signatures use the current version, and
175
+ each ciphertext records the version that produced it, so data encrypted
176
+ before a rotation still decrypts and signatures made before it still
177
+ verify. `getKey` reports `currentVersion`; `encrypt` and `decrypt`
178
+ report `keyVersion`.
179
+
180
+ A version stays usable until you destroy it with
181
+ `destroyKeyVersion(keyId, version)`. After that, ciphertext from that
182
+ version rejects with `VERSION_DESTROYED` and its signatures no longer
183
+ verify. The current version cannot be destroyed; rotate first.
184
+ `disableKey` and `scheduleKeyDeletion` still block every operation on
185
+ the key, all versions included.
186
+
187
+ ```ts
188
+ const key = await kms.createKey("aes-256-gcm", "encrypt");
189
+ const old = await kms.encrypt(key.keyId, data); // old.keyVersion === 1
190
+ await kms.rotateKey(key.keyId); // currentVersion === 2
191
+ await kms.decrypt(key.keyId, old.ciphertext); // still decrypts with version 1
192
+ await kms.destroyKeyVersion(key.keyId, 1); // version 1 is gone for good
193
+ ```
194
+
195
+ The ciphertext of these two providers is the base64 of: a format byte
196
+ (`0x01`), the key version (4 bytes, big-endian), the AES-GCM IV (12
197
+ bytes), the tag (16 bytes) and the AES-256-GCM ciphertext. Ciphertext
198
+ produced by 0.0.6 and earlier is not accepted; neither provider persists
199
+ keys, so none can outlive the process that made it.
200
+
201
+ ### Encryption context
202
+
203
+ The encryption context is bound to the ciphertext as AES-GCM additional
204
+ authenticated data. It is canonicalised first (entries sorted by key),
205
+ so `{ a: "1", b: "2" }` and `{ b: "2", a: "1" }` are the same context.
206
+ Values must be strings; anything else rejects with `INVALID_ARGUMENT`.
207
+ An empty context is the same as no context.
208
+
209
+ ### Errors
210
+
211
+ Providers reject with `KmsError`, which extends `Error` and carries a
212
+ `code` (and the `keyId` when there is one). Branch on the code, not the
213
+ message:
214
+
215
+ | Code | Meaning |
216
+ | :------------------- | :------------------------------------------------------------- |
217
+ | `NOT_FOUND` | Unknown key, or a ciphertext names a version the key never had |
218
+ | `DISABLED` | The key is disabled or scheduled for deletion |
219
+ | `INVALID_USAGE` | The key's usage does not allow the operation |
220
+ | `INVALID_ARGUMENT` | Malformed argument, or destroying the current version |
221
+ | `INVALID_CIPHERTEXT` | Truncated ciphertext or an unknown format |
222
+ | `DECRYPTION_FAILED` | Wrong context, wrong key, or tampered ciphertext |
223
+ | `VERSION_DESTROYED` | The ciphertext's key version has been destroyed |
224
+ | `NOT_IMPLEMENTED` | Stub provider (GCP, Azure, Vault) |
225
+ | `DEPENDENCY_MISSING` | The AWS SDK peer dependency is not installed |
226
+
227
+ Errors raised by the AWS SDK itself are passed through unchanged. No
228
+ provider method takes a timeout or an `AbortSignal` yet.
229
+
230
+ <p align="right"><a href="#contents">Back to Top</a></p>
231
+
232
+ ## Authentication
233
+
234
+ | Provider | Credentials |
235
+ | :-------- | :--------------------------------------------------------------------------------- |
236
+ | **AWS** | Pass `credentials` in `AwsKmsOptions`, or rely on the default AWS credential chain |
237
+ | **GCP** | Not applicable yet (stub provider) |
238
+ | **Azure** | Not applicable yet (stub provider) |
239
+ | **Vault** | Not applicable yet (stub provider) |
240
+ | **Local** | No authentication required |
241
+
242
+ <p align="right"><a href="#contents">Back to Top</a></p>
243
+
244
+ ## Examples
245
+
246
+ All examples are self-contained TypeScript files in the `examples/`
247
+ directory. Run any example with:
248
+
249
+ ```bash
250
+ npx ts-node examples/<name>.ts
251
+ ```
252
+
253
+ | Category | Example | Purpose |
254
+ | :------- | :---------------------------------- | :------------------------------------------------------- |
255
+ | Local | [local.ts](examples/local.ts) | Create keys, encrypt/decrypt with the in-memory provider |
256
+ | AWS | [aws.ts](examples/aws.ts) | AWS KMS setup and usage pattern |
257
+ | Envelope | [envelope.ts](examples/envelope.ts) | Envelope encryption with `generateDataKey` |
258
+ | Rotation | [rotation.ts](examples/rotation.ts) | Rotate, decrypt old data, destroy a retired version |
259
+ | Multi | [multi.ts](examples/multi.ts) | Provider-agnostic code across multiple backends |
260
+
261
+ <p align="right"><a href="#contents">Back to Top</a></p>
262
+
263
+ <p align="right"><a href="#contents">Back to Top</a></p>
264
+
265
+ ---
266
+
267
+ ## Development
268
+
269
+ ```bash
270
+ pnpm --filter @sebastienrousseau/crypto-kms run build
271
+ pnpm --filter @sebastienrousseau/crypto-kms run test
272
+ pnpm --filter @sebastienrousseau/crypto-kms run lint
273
+ pnpm --filter @sebastienrousseau/crypto-kms run format
274
+ ```
275
+
276
+ All 18 packages in the Crypto Service workspace maintain a **100% coverage floor** across statements, branches, functions, and lines.
277
+
278
+ <p align="right"><a href="#contents">Back to Top</a></p>
279
+
280
+ ---
281
+
282
+ ## Security
283
+
284
+ Report vulnerabilities privately via [GitHub Security Advisories](https://github.com/sebastienrousseau/crypto-service/security/advisories) or according to [`SECURITY.md`](../../SECURITY.md). Never report security issues publicly.
285
+
286
+ The local and simulated PKCS#11 providers run AES-256-GCM through Node.js `crypto` and Ed25519 through crypto-lib (`@noble/curves`). Neither is a validated cryptographic module, and neither zeroes key material held in memory.
287
+
288
+ <p align="right"><a href="#contents">Back to Top</a></p>
289
+
290
+ ---
291
+
292
+ ## Documentation
293
+
294
+ - [Full Suite Documentation](https://sebastienrousseau.github.io/crypto-service/)
295
+ - [API Reference (TypeDoc)](https://sebastienrousseau.github.io/crypto-service/)
296
+ - [Developer Guide](../../DEVELOPMENT.md)
297
+ - [Security Policy](../../SECURITY.md)
298
+ - [Architecture & Design](../../ARCHITECTURE.md)
299
+
300
+ <p align="right"><a href="#contents">Back to Top</a></p>
301
+
302
+ ---
303
+
304
+ ## Stability guarantees
305
+
306
+ Versions advance strictly one step at a time on the `0.0.x` line (`v0.0.1` → `v0.0.2` → `v0.0.3` ... → `v0.0.999` → `v0.1.0`). Work for every release iteration begins on a dedicated `feat/v<version>` branch.
307
+
308
+ All 18 packages in the workspace move in lockstep. Public API signatures, cipher output formats, and serialization schemas are strictly versioned. Breaking changes to serialized formats or algorithm defaults are considered major breaking changes. Minimum toolchain upgrades (e.g. Node.js LTS floor) are governed by [POLICIES.md](../../docs/POLICIES.md).
309
+
310
+ <p align="right"><a href="#contents">Back to Top</a></p>
311
+
312
+ ---
313
+
314
+ ## License
315
+
316
+ Dual-licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) or [MIT](https://opensource.org/licenses/MIT), at your option.
317
+
318
+ Copyright (c) 2022-2026 Sebastien Rousseau and The Crypto Service Suite contributors.
319
+
320
+ <p align="right"><a href="#contents">Back to Top</a></p>
@@ -0,0 +1,8 @@
1
+ export type KmsErrorCode = "NOT_FOUND" | "DISABLED" | "INVALID_USAGE" | "INVALID_ARGUMENT" | "INVALID_CIPHERTEXT" | "DECRYPTION_FAILED" | "VERSION_DESTROYED" | "NOT_IMPLEMENTED" | "DEPENDENCY_MISSING";
2
+ export declare class KmsError extends Error {
3
+ readonly name = "KmsError";
4
+ readonly code: KmsErrorCode;
5
+ readonly keyId: string | undefined;
6
+ constructor(code: KmsErrorCode, message: string, keyId?: string);
7
+ }
8
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,YAAY,GACpB,WAAW,GACX,UAAU,GACV,eAAe,GACf,kBAAkB,GAClB,oBAAoB,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,iBAAiB,GACjB,oBAAoB,CAAC;AAmBzB,qBAAa,QAAS,SAAQ,KAAK;IAEjC,SAAkB,IAAI,cAAc;IAEpC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAE5B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGvB,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAKhE"}
package/dist/errors.js ADDED
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.KmsError = void 0;
4
+ class KmsError extends Error {
5
+ name = "KmsError";
6
+ code;
7
+ keyId;
8
+ constructor(code, message, keyId) {
9
+ super(message);
10
+ this.code = code;
11
+ this.keyId = keyId;
12
+ }
13
+ }
14
+ exports.KmsError = KmsError;
15
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1,15 @@
1
+ export type { KmsProvider, KmsKeyMetadata, KmsEncryptResult, KmsDecryptResult, KmsSignResult, } from "./types";
2
+ export { KmsError } from "./errors";
3
+ export type { KmsErrorCode } from "./errors";
4
+ export { AwsKmsProvider } from "./providers/aws";
5
+ export type { AwsKmsOptions } from "./providers/aws";
6
+ export { GcpKmsProvider } from "./providers/gcp";
7
+ export type { GcpKmsOptions } from "./providers/gcp";
8
+ export { AzureKmsProvider } from "./providers/azure";
9
+ export type { AzureKmsOptions } from "./providers/azure";
10
+ export { VaultKmsProvider } from "./providers/vault";
11
+ export type { VaultKmsOptions } from "./providers/vault";
12
+ export { LocalKmsProvider } from "./providers/local";
13
+ export { Pkcs11HsmProvider } from "./providers/pkcs11";
14
+ export type { Pkcs11HsmOptions, HsmSessionInfo } from "./providers/pkcs11";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,YAAY,EACV,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Pkcs11HsmProvider = exports.LocalKmsProvider = exports.VaultKmsProvider = exports.AzureKmsProvider = exports.GcpKmsProvider = exports.AwsKmsProvider = exports.KmsError = void 0;
4
+ var errors_1 = require("./errors");
5
+ Object.defineProperty(exports, "KmsError", { enumerable: true, get: function () { return errors_1.KmsError; } });
6
+ var aws_1 = require("./providers/aws");
7
+ Object.defineProperty(exports, "AwsKmsProvider", { enumerable: true, get: function () { return aws_1.AwsKmsProvider; } });
8
+ var gcp_1 = require("./providers/gcp");
9
+ Object.defineProperty(exports, "GcpKmsProvider", { enumerable: true, get: function () { return gcp_1.GcpKmsProvider; } });
10
+ var azure_1 = require("./providers/azure");
11
+ Object.defineProperty(exports, "AzureKmsProvider", { enumerable: true, get: function () { return azure_1.AzureKmsProvider; } });
12
+ var vault_1 = require("./providers/vault");
13
+ Object.defineProperty(exports, "VaultKmsProvider", { enumerable: true, get: function () { return vault_1.VaultKmsProvider; } });
14
+ var local_1 = require("./providers/local");
15
+ Object.defineProperty(exports, "LocalKmsProvider", { enumerable: true, get: function () { return local_1.LocalKmsProvider; } });
16
+ var pkcs11_1 = require("./providers/pkcs11");
17
+ Object.defineProperty(exports, "Pkcs11HsmProvider", { enumerable: true, get: function () { return pkcs11_1.Pkcs11HsmProvider; } });
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,36 @@
1
+ import type { KmsProvider, KmsKeyMetadata, KmsEncryptResult, KmsDecryptResult, KmsSignResult } from "../types";
2
+ export interface AwsKmsOptions {
3
+ region: string;
4
+ credentials?: {
5
+ accessKeyId: string;
6
+ secretAccessKey: string;
7
+ sessionToken?: string;
8
+ };
9
+ endpoint?: string;
10
+ }
11
+ export declare class AwsKmsProvider implements KmsProvider {
12
+ readonly name = "aws";
13
+ private readonly options;
14
+ private client;
15
+ constructor(options: AwsKmsOptions);
16
+ private getClient;
17
+ listKeys(_filters?: {
18
+ usage?: string;
19
+ enabled?: boolean;
20
+ }): Promise<KmsKeyMetadata[]>;
21
+ getKey(keyId: string): Promise<KmsKeyMetadata>;
22
+ createKey(algorithm: string, usage: "encrypt" | "sign" | "wrap", metadata?: Record<string, string>): Promise<KmsKeyMetadata>;
23
+ enableKey(keyId: string): Promise<void>;
24
+ disableKey(keyId: string): Promise<void>;
25
+ scheduleKeyDeletion(keyId: string, pendingWindowDays?: number): Promise<void>;
26
+ encrypt(keyId: string, plaintext: Uint8Array, context?: Record<string, string>): Promise<KmsEncryptResult>;
27
+ decrypt(keyId: string, ciphertext: string, context?: Record<string, string>): Promise<KmsDecryptResult>;
28
+ sign(keyId: string, data: Uint8Array, algorithm?: string): Promise<KmsSignResult>;
29
+ verify(keyId: string, data: Uint8Array, signature: string, algorithm?: string): Promise<boolean>;
30
+ rotateKey(keyId: string): Promise<KmsKeyMetadata>;
31
+ generateDataKey(keyId: string, keySpec?: string): Promise<{
32
+ plaintext: Uint8Array;
33
+ ciphertext: string;
34
+ }>;
35
+ }
36
+ //# sourceMappingURL=aws.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aws.d.ts","sourceRoot":"","sources":["../../src/providers/aws.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACd,MAAM,UAAU,CAAC;AAkBlB,MAAM,WAAW,aAAa;IAE5B,MAAM,EAAE,MAAM,CAAC;IAEf,WAAW,CAAC,EAAE;QAEZ,WAAW,EAAE,MAAM,CAAC;QAEpB,eAAe,EAAE,MAAM,CAAC;QAExB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IAEF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqBD,qBAAa,cAAe,YAAW,WAAW;IAEhD,QAAQ,CAAC,IAAI,SAAS;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IAExC,OAAO,CAAC,MAAM,CAAsB;gBAGxB,OAAO,EAAE,aAAa;YAMpB,SAAS;IAqBjB,QAAQ,CAAC,QAAQ,CAAC,EAAE;QACxB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,OAAO,CAAC;KACnB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAevB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgB9C,SAAS,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,EAClC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC;IA+BpB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,iBAAiB,SAAK,GACrB,OAAO,CAAC,IAAI,CAAC;IAYV,OAAO,CACX,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,UAAU,EACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAqBtB,OAAO,CACX,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAiBtB,IAAI,CACR,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,UAAU,EAChB,SAAS,SAAuB,GAC/B,OAAO,CAAC,aAAa,CAAC;IAmBnB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,SAAuB,GAC/B,OAAO,CAAC,OAAO,CAAC;IAgBb,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQjD,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,OAAO,SAAY,GAClB,OAAO,CAAC;QAET,SAAS,EAAE,UAAU,CAAC;QAEtB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CAcH"}
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AwsKmsProvider = void 0;
37
+ const errors_1 = require("../errors");
38
+ const AWS_SDK_MISSING = "AWS KMS requires @aws-sdk/client-kms. Install it: npm install @aws-sdk/client-kms";
39
+ class AwsKmsProvider {
40
+ name = "aws";
41
+ options;
42
+ client;
43
+ constructor(options) {
44
+ this.options = options;
45
+ this.client = null;
46
+ }
47
+ async getClient() {
48
+ if (!this.client) {
49
+ try {
50
+ const mod = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
51
+ const config = { region: this.options.region };
52
+ if (this.options.credentials) {
53
+ config.credentials = this.options.credentials;
54
+ }
55
+ if (this.options.endpoint) {
56
+ config.endpoint = this.options.endpoint;
57
+ }
58
+ this.client = new mod.KMSClient(config);
59
+ }
60
+ catch {
61
+ throw new errors_1.KmsError("DEPENDENCY_MISSING", AWS_SDK_MISSING);
62
+ }
63
+ }
64
+ return this.client;
65
+ }
66
+ async listKeys(_filters) {
67
+ const client = await this.getClient();
68
+ const { ListKeysCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
69
+ const result = await client.send(new ListKeysCommand({}));
70
+ return (result.Keys ?? []).map((k) => ({
71
+ keyId: k.KeyId ?? "",
72
+ algorithm: "unknown",
73
+ usage: "encrypt",
74
+ createdAt: new Date().toISOString(),
75
+ enabled: true,
76
+ provider: "aws",
77
+ }));
78
+ }
79
+ async getKey(keyId) {
80
+ const client = await this.getClient();
81
+ const { DescribeKeyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
82
+ const result = await client.send(new DescribeKeyCommand({ KeyId: keyId }));
83
+ const meta = result.KeyMetadata;
84
+ return {
85
+ keyId: meta?.KeyId ?? keyId,
86
+ algorithm: meta?.KeySpec ?? "unknown",
87
+ usage: meta?.KeyUsage === "SIGN_VERIFY" ? "sign" : "encrypt",
88
+ createdAt: meta?.CreationDate?.toISOString() ?? new Date().toISOString(),
89
+ enabled: meta?.Enabled ?? true,
90
+ provider: "aws",
91
+ };
92
+ }
93
+ async createKey(algorithm, usage, metadata) {
94
+ const client = await this.getClient();
95
+ const { CreateKeyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
96
+ const keySpec = algorithm.toUpperCase().replace(/-/g, "_");
97
+ const result = await client.send(new CreateKeyCommand({
98
+ KeyUsage: usage === "sign" ? "SIGN_VERIFY" : "ENCRYPT_DECRYPT",
99
+ KeySpec: keySpec,
100
+ ...(metadata
101
+ ? {
102
+ Tags: Object.entries(metadata).map(([k, v]) => ({
103
+ TagKey: k,
104
+ TagValue: v,
105
+ })),
106
+ }
107
+ : {}),
108
+ }));
109
+ return {
110
+ keyId: result.KeyMetadata?.KeyId ?? "",
111
+ algorithm,
112
+ usage,
113
+ createdAt: result.KeyMetadata?.CreationDate?.toISOString() ??
114
+ new Date().toISOString(),
115
+ enabled: true,
116
+ provider: "aws",
117
+ };
118
+ }
119
+ async enableKey(keyId) {
120
+ const client = await this.getClient();
121
+ const { EnableKeyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
122
+ await client.send(new EnableKeyCommand({ KeyId: keyId }));
123
+ }
124
+ async disableKey(keyId) {
125
+ const client = await this.getClient();
126
+ const { DisableKeyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
127
+ await client.send(new DisableKeyCommand({ KeyId: keyId }));
128
+ }
129
+ async scheduleKeyDeletion(keyId, pendingWindowDays = 30) {
130
+ const client = await this.getClient();
131
+ const { ScheduleKeyDeletionCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
132
+ await client.send(new ScheduleKeyDeletionCommand({
133
+ KeyId: keyId,
134
+ PendingWindowInDays: pendingWindowDays,
135
+ }));
136
+ }
137
+ async encrypt(keyId, plaintext, context) {
138
+ const client = await this.getClient();
139
+ const { EncryptCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
140
+ const result = await client.send(new EncryptCommand({
141
+ KeyId: keyId,
142
+ Plaintext: plaintext,
143
+ ...(context ? { EncryptionContext: context } : {}),
144
+ }));
145
+ const out = {
146
+ ciphertext: Buffer.from(result.CiphertextBlob).toString("base64"),
147
+ keyId: result.KeyId ?? keyId,
148
+ };
149
+ if (context) {
150
+ out.context = context;
151
+ }
152
+ return out;
153
+ }
154
+ async decrypt(keyId, ciphertext, context) {
155
+ const client = await this.getClient();
156
+ const { DecryptCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
157
+ const result = await client.send(new DecryptCommand({
158
+ KeyId: keyId,
159
+ CiphertextBlob: Buffer.from(ciphertext, "base64"),
160
+ ...(context ? { EncryptionContext: context } : {}),
161
+ }));
162
+ return {
163
+ plaintext: new Uint8Array(result.Plaintext),
164
+ keyId: result.KeyId ?? keyId,
165
+ };
166
+ }
167
+ async sign(keyId, data, algorithm = "RSASSA_PSS_SHA_256") {
168
+ const client = await this.getClient();
169
+ const { SignCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
170
+ const result = await client.send(new SignCommand({
171
+ KeyId: keyId,
172
+ Message: data,
173
+ MessageType: "RAW",
174
+ SigningAlgorithm: algorithm,
175
+ }));
176
+ return {
177
+ signature: Buffer.from(result.Signature).toString("base64"),
178
+ keyId: result.KeyId ?? keyId,
179
+ algorithm: result.SigningAlgorithm ?? algorithm,
180
+ };
181
+ }
182
+ async verify(keyId, data, signature, algorithm = "RSASSA_PSS_SHA_256") {
183
+ const client = await this.getClient();
184
+ const { VerifyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
185
+ const result = await client.send(new VerifyCommand({
186
+ KeyId: keyId,
187
+ Message: data,
188
+ MessageType: "RAW",
189
+ Signature: Buffer.from(signature, "base64"),
190
+ SigningAlgorithm: algorithm,
191
+ }));
192
+ return result.SignatureValid ?? false;
193
+ }
194
+ async rotateKey(keyId) {
195
+ const client = await this.getClient();
196
+ const { EnableKeyRotationCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
197
+ await client.send(new EnableKeyRotationCommand({ KeyId: keyId }));
198
+ return this.getKey(keyId);
199
+ }
200
+ async generateDataKey(keyId, keySpec = "AES_256") {
201
+ const client = await this.getClient();
202
+ const { GenerateDataKeyCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-kms")));
203
+ const result = await client.send(new GenerateDataKeyCommand({
204
+ KeyId: keyId,
205
+ KeySpec: keySpec,
206
+ }));
207
+ return {
208
+ plaintext: new Uint8Array(result.Plaintext),
209
+ ciphertext: Buffer.from(result.CiphertextBlob).toString("base64"),
210
+ };
211
+ }
212
+ }
213
+ exports.AwsKmsProvider = AwsKmsProvider;
214
+ //# sourceMappingURL=aws.js.map