vaultkeeper 0.2.0 → 0.4.0
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/dist/index.cjs +124 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +117 -1
- package/dist/index.d.ts +117 -1
- package/dist/index.js +123 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -287,6 +287,59 @@ interface SecretAccessor {
|
|
|
287
287
|
*/
|
|
288
288
|
read(callback: (buf: Buffer) => void): void;
|
|
289
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Request for delegated signing.
|
|
292
|
+
*
|
|
293
|
+
* The `data` field is the payload to sign. Strings are UTF-8-encoded
|
|
294
|
+
* before signing.
|
|
295
|
+
*/
|
|
296
|
+
interface SignRequest {
|
|
297
|
+
/** The data to sign. Strings are treated as UTF-8. */
|
|
298
|
+
data: string | Buffer;
|
|
299
|
+
/**
|
|
300
|
+
* Override the hash algorithm (`'sha256'`, `'sha384'`, or `'sha512'`).
|
|
301
|
+
* Ignored for Ed25519/Ed448 keys where the algorithm is implicit.
|
|
302
|
+
* Non-Edwards keys (RSA, EC) default to `'sha256'` when omitted.
|
|
303
|
+
* Weak algorithms (e.g. `'md5'`, `'sha1'`) are rejected.
|
|
304
|
+
*/
|
|
305
|
+
algorithm?: string | undefined;
|
|
306
|
+
}
|
|
307
|
+
/** Result from a delegated signing operation. */
|
|
308
|
+
interface SignResult {
|
|
309
|
+
/** Base64-encoded signature. */
|
|
310
|
+
signature: string;
|
|
311
|
+
/**
|
|
312
|
+
* Algorithm label describing how the signature was produced.
|
|
313
|
+
* For Edwards keys this is the key type (e.g. `'ed25519'`).
|
|
314
|
+
* For other keys this matches the `algorithm` field from the request
|
|
315
|
+
* (or the default `'sha256'`).
|
|
316
|
+
*/
|
|
317
|
+
algorithm: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Request for signature verification.
|
|
321
|
+
*
|
|
322
|
+
* This is a static operation that only requires public key material —
|
|
323
|
+
* no VaultKeeper instance or capability token is needed.
|
|
324
|
+
*/
|
|
325
|
+
interface VerifyRequest {
|
|
326
|
+
/** The original data that was signed. Strings are treated as UTF-8. */
|
|
327
|
+
data: string | Buffer;
|
|
328
|
+
/** Base64-encoded signature to verify. */
|
|
329
|
+
signature: string;
|
|
330
|
+
/**
|
|
331
|
+
* PEM-encoded public key (SPKI format) as a string.
|
|
332
|
+
*
|
|
333
|
+
* Other `KeyLike` formats supported by `crypto.createPublicKey()` are not
|
|
334
|
+
* accepted by this interface.
|
|
335
|
+
*/
|
|
336
|
+
publicKey: string;
|
|
337
|
+
/**
|
|
338
|
+
* Override the hash algorithm. Ignored for Ed25519/Ed448 keys.
|
|
339
|
+
* Non-Edwards keys default to `'sha256'` when omitted.
|
|
340
|
+
*/
|
|
341
|
+
algorithm?: string | undefined;
|
|
342
|
+
}
|
|
290
343
|
/** Vaultkeeper configuration file structure. */
|
|
291
344
|
interface VaultConfig {
|
|
292
345
|
/** Config schema version. Currently must be `1`. */
|
|
@@ -379,6 +432,22 @@ interface SecretBackend {
|
|
|
379
432
|
*/
|
|
380
433
|
exists(id: string): Promise<boolean>;
|
|
381
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* Backend that can enumerate stored secret IDs.
|
|
437
|
+
* @public
|
|
438
|
+
*/
|
|
439
|
+
interface ListableBackend extends SecretBackend {
|
|
440
|
+
/**
|
|
441
|
+
* List IDs of all secrets managed by this backend.
|
|
442
|
+
* @returns Array of secret identifiers
|
|
443
|
+
*/
|
|
444
|
+
list(): Promise<string[]>;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Type guard for backends that support listing.
|
|
448
|
+
* @public
|
|
449
|
+
*/
|
|
450
|
+
declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
|
|
382
451
|
|
|
383
452
|
/**
|
|
384
453
|
* Registry for secret backend implementations.
|
|
@@ -418,6 +487,19 @@ declare class BackendRegistry {
|
|
|
418
487
|
* @returns Array of backend type identifiers
|
|
419
488
|
*/
|
|
420
489
|
static getTypes(): string[];
|
|
490
|
+
/**
|
|
491
|
+
* Returns backend types that are available on the current system.
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* Creates each registered backend via its factory, calls `isAvailable()`,
|
|
495
|
+
* and returns only the type identifiers whose backend reports availability.
|
|
496
|
+
* If a backend's `isAvailable()` call throws, that backend is excluded from
|
|
497
|
+
* the result rather than propagating the error.
|
|
498
|
+
*
|
|
499
|
+
* @returns Promise resolving to an array of available backend type identifiers
|
|
500
|
+
* @public
|
|
501
|
+
*/
|
|
502
|
+
static getAvailableTypes(): Promise<string[]>;
|
|
421
503
|
}
|
|
422
504
|
|
|
423
505
|
/**
|
|
@@ -549,6 +631,40 @@ declare class VaultKeeper {
|
|
|
549
631
|
* instance.
|
|
550
632
|
*/
|
|
551
633
|
getSecret(token: CapabilityToken): SecretAccessor;
|
|
634
|
+
/**
|
|
635
|
+
* Sign data using the private key embedded in a capability token.
|
|
636
|
+
*
|
|
637
|
+
* The signing key is extracted from the token's encrypted claims, used
|
|
638
|
+
* for a single `crypto.sign()` call, and never exposed to the caller.
|
|
639
|
+
* The algorithm is auto-detected from the key type unless overridden
|
|
640
|
+
* in the request.
|
|
641
|
+
*
|
|
642
|
+
* @param token - A `CapabilityToken` obtained from `authorize()`.
|
|
643
|
+
* @param request - The data to sign and optional algorithm override.
|
|
644
|
+
* @returns The base64-encoded signature and algorithm label, together
|
|
645
|
+
* with the vault metadata (`vaultResponse`).
|
|
646
|
+
* @throws {VaultError} If `token` is invalid or was not created by this
|
|
647
|
+
* vault instance.
|
|
648
|
+
*/
|
|
649
|
+
sign(token: CapabilityToken, request: SignRequest): Promise<{
|
|
650
|
+
result: SignResult;
|
|
651
|
+
vaultResponse: VaultResponse;
|
|
652
|
+
}>;
|
|
653
|
+
/**
|
|
654
|
+
* Verify a signature using a public key.
|
|
655
|
+
*
|
|
656
|
+
* This is a static method — no VaultKeeper instance, secrets, or
|
|
657
|
+
* capability tokens are required. It is safe to call from CI or any
|
|
658
|
+
* context that has access to public key material.
|
|
659
|
+
*
|
|
660
|
+
* Never throws. Returns `false` for invalid key material, malformed
|
|
661
|
+
* signatures, or any verification failure.
|
|
662
|
+
*
|
|
663
|
+
* @param request - The data, signature, public key, and optional
|
|
664
|
+
* algorithm override.
|
|
665
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
666
|
+
*/
|
|
667
|
+
static verify(request: VerifyRequest): boolean;
|
|
552
668
|
/**
|
|
553
669
|
* Rotate the current encryption key.
|
|
554
670
|
*
|
|
@@ -584,4 +700,4 @@ declare class VaultKeeper {
|
|
|
584
700
|
setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
|
|
585
701
|
}
|
|
586
702
|
|
|
587
|
-
export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse };
|
|
703
|
+
export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, type SignRequest, type SignResult, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, type VerifyRequest, isListableBackend };
|
package/dist/index.d.ts
CHANGED
|
@@ -287,6 +287,59 @@ interface SecretAccessor {
|
|
|
287
287
|
*/
|
|
288
288
|
read(callback: (buf: Buffer) => void): void;
|
|
289
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Request for delegated signing.
|
|
292
|
+
*
|
|
293
|
+
* The `data` field is the payload to sign. Strings are UTF-8-encoded
|
|
294
|
+
* before signing.
|
|
295
|
+
*/
|
|
296
|
+
interface SignRequest {
|
|
297
|
+
/** The data to sign. Strings are treated as UTF-8. */
|
|
298
|
+
data: string | Buffer;
|
|
299
|
+
/**
|
|
300
|
+
* Override the hash algorithm (`'sha256'`, `'sha384'`, or `'sha512'`).
|
|
301
|
+
* Ignored for Ed25519/Ed448 keys where the algorithm is implicit.
|
|
302
|
+
* Non-Edwards keys (RSA, EC) default to `'sha256'` when omitted.
|
|
303
|
+
* Weak algorithms (e.g. `'md5'`, `'sha1'`) are rejected.
|
|
304
|
+
*/
|
|
305
|
+
algorithm?: string | undefined;
|
|
306
|
+
}
|
|
307
|
+
/** Result from a delegated signing operation. */
|
|
308
|
+
interface SignResult {
|
|
309
|
+
/** Base64-encoded signature. */
|
|
310
|
+
signature: string;
|
|
311
|
+
/**
|
|
312
|
+
* Algorithm label describing how the signature was produced.
|
|
313
|
+
* For Edwards keys this is the key type (e.g. `'ed25519'`).
|
|
314
|
+
* For other keys this matches the `algorithm` field from the request
|
|
315
|
+
* (or the default `'sha256'`).
|
|
316
|
+
*/
|
|
317
|
+
algorithm: string;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Request for signature verification.
|
|
321
|
+
*
|
|
322
|
+
* This is a static operation that only requires public key material —
|
|
323
|
+
* no VaultKeeper instance or capability token is needed.
|
|
324
|
+
*/
|
|
325
|
+
interface VerifyRequest {
|
|
326
|
+
/** The original data that was signed. Strings are treated as UTF-8. */
|
|
327
|
+
data: string | Buffer;
|
|
328
|
+
/** Base64-encoded signature to verify. */
|
|
329
|
+
signature: string;
|
|
330
|
+
/**
|
|
331
|
+
* PEM-encoded public key (SPKI format) as a string.
|
|
332
|
+
*
|
|
333
|
+
* Other `KeyLike` formats supported by `crypto.createPublicKey()` are not
|
|
334
|
+
* accepted by this interface.
|
|
335
|
+
*/
|
|
336
|
+
publicKey: string;
|
|
337
|
+
/**
|
|
338
|
+
* Override the hash algorithm. Ignored for Ed25519/Ed448 keys.
|
|
339
|
+
* Non-Edwards keys default to `'sha256'` when omitted.
|
|
340
|
+
*/
|
|
341
|
+
algorithm?: string | undefined;
|
|
342
|
+
}
|
|
290
343
|
/** Vaultkeeper configuration file structure. */
|
|
291
344
|
interface VaultConfig {
|
|
292
345
|
/** Config schema version. Currently must be `1`. */
|
|
@@ -379,6 +432,22 @@ interface SecretBackend {
|
|
|
379
432
|
*/
|
|
380
433
|
exists(id: string): Promise<boolean>;
|
|
381
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* Backend that can enumerate stored secret IDs.
|
|
437
|
+
* @public
|
|
438
|
+
*/
|
|
439
|
+
interface ListableBackend extends SecretBackend {
|
|
440
|
+
/**
|
|
441
|
+
* List IDs of all secrets managed by this backend.
|
|
442
|
+
* @returns Array of secret identifiers
|
|
443
|
+
*/
|
|
444
|
+
list(): Promise<string[]>;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Type guard for backends that support listing.
|
|
448
|
+
* @public
|
|
449
|
+
*/
|
|
450
|
+
declare function isListableBackend(backend: SecretBackend): backend is ListableBackend;
|
|
382
451
|
|
|
383
452
|
/**
|
|
384
453
|
* Registry for secret backend implementations.
|
|
@@ -418,6 +487,19 @@ declare class BackendRegistry {
|
|
|
418
487
|
* @returns Array of backend type identifiers
|
|
419
488
|
*/
|
|
420
489
|
static getTypes(): string[];
|
|
490
|
+
/**
|
|
491
|
+
* Returns backend types that are available on the current system.
|
|
492
|
+
*
|
|
493
|
+
* @remarks
|
|
494
|
+
* Creates each registered backend via its factory, calls `isAvailable()`,
|
|
495
|
+
* and returns only the type identifiers whose backend reports availability.
|
|
496
|
+
* If a backend's `isAvailable()` call throws, that backend is excluded from
|
|
497
|
+
* the result rather than propagating the error.
|
|
498
|
+
*
|
|
499
|
+
* @returns Promise resolving to an array of available backend type identifiers
|
|
500
|
+
* @public
|
|
501
|
+
*/
|
|
502
|
+
static getAvailableTypes(): Promise<string[]>;
|
|
421
503
|
}
|
|
422
504
|
|
|
423
505
|
/**
|
|
@@ -549,6 +631,40 @@ declare class VaultKeeper {
|
|
|
549
631
|
* instance.
|
|
550
632
|
*/
|
|
551
633
|
getSecret(token: CapabilityToken): SecretAccessor;
|
|
634
|
+
/**
|
|
635
|
+
* Sign data using the private key embedded in a capability token.
|
|
636
|
+
*
|
|
637
|
+
* The signing key is extracted from the token's encrypted claims, used
|
|
638
|
+
* for a single `crypto.sign()` call, and never exposed to the caller.
|
|
639
|
+
* The algorithm is auto-detected from the key type unless overridden
|
|
640
|
+
* in the request.
|
|
641
|
+
*
|
|
642
|
+
* @param token - A `CapabilityToken` obtained from `authorize()`.
|
|
643
|
+
* @param request - The data to sign and optional algorithm override.
|
|
644
|
+
* @returns The base64-encoded signature and algorithm label, together
|
|
645
|
+
* with the vault metadata (`vaultResponse`).
|
|
646
|
+
* @throws {VaultError} If `token` is invalid or was not created by this
|
|
647
|
+
* vault instance.
|
|
648
|
+
*/
|
|
649
|
+
sign(token: CapabilityToken, request: SignRequest): Promise<{
|
|
650
|
+
result: SignResult;
|
|
651
|
+
vaultResponse: VaultResponse;
|
|
652
|
+
}>;
|
|
653
|
+
/**
|
|
654
|
+
* Verify a signature using a public key.
|
|
655
|
+
*
|
|
656
|
+
* This is a static method — no VaultKeeper instance, secrets, or
|
|
657
|
+
* capability tokens are required. It is safe to call from CI or any
|
|
658
|
+
* context that has access to public key material.
|
|
659
|
+
*
|
|
660
|
+
* Never throws. Returns `false` for invalid key material, malformed
|
|
661
|
+
* signatures, or any verification failure.
|
|
662
|
+
*
|
|
663
|
+
* @param request - The data, signature, public key, and optional
|
|
664
|
+
* algorithm override.
|
|
665
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
666
|
+
*/
|
|
667
|
+
static verify(request: VerifyRequest): boolean;
|
|
552
668
|
/**
|
|
553
669
|
* Rotate the current encryption key.
|
|
554
670
|
*
|
|
@@ -584,4 +700,4 @@ declare class VaultKeeper {
|
|
|
584
700
|
setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void>;
|
|
585
701
|
}
|
|
586
702
|
|
|
587
|
-
export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse };
|
|
703
|
+
export { AuthorizationDeniedError, type BackendConfig, type BackendFactory, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, type ExecRequest, type ExecResult, type FetchRequest, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, type KeyStatus, type ListableBackend, PluginNotFoundError, type PreflightCheck, type PreflightCheckStatus, type PreflightResult, RotationInProgressError, type SecretAccessor, type SecretBackend, SecretNotFoundError, SetupError, type SetupOptions, type SignRequest, type SignResult, TokenExpiredError, TokenRevokedError, type TrustTier, UsageLimitExceededError, type VaultConfig, VaultError, VaultKeeper, type VaultKeeperOptions, type VaultResponse, type VerifyRequest, isListableBackend };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { spawn } from 'child_process';
|
|
|
2
2
|
import * as fs5 from 'fs/promises';
|
|
3
3
|
import * as path5 from 'path';
|
|
4
4
|
import * as os4 from 'os';
|
|
5
|
-
import * as
|
|
5
|
+
import * as crypto4 from 'crypto';
|
|
6
6
|
import * as fs4 from 'fs';
|
|
7
7
|
import { CompactEncrypt, compactDecrypt } from 'jose';
|
|
8
8
|
|
|
@@ -171,6 +171,11 @@ var RotationInProgressError = class extends VaultError {
|
|
|
171
171
|
}
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
+
// src/backend/types.ts
|
|
175
|
+
function isListableBackend(backend) {
|
|
176
|
+
return "list" in backend && typeof backend.list === "function";
|
|
177
|
+
}
|
|
178
|
+
|
|
174
179
|
// src/backend/registry.ts
|
|
175
180
|
var BackendRegistry = class {
|
|
176
181
|
static backends = /* @__PURE__ */ new Map();
|
|
@@ -206,6 +211,33 @@ var BackendRegistry = class {
|
|
|
206
211
|
static getTypes() {
|
|
207
212
|
return Array.from(this.backends.keys());
|
|
208
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Returns backend types that are available on the current system.
|
|
216
|
+
*
|
|
217
|
+
* @remarks
|
|
218
|
+
* Creates each registered backend via its factory, calls `isAvailable()`,
|
|
219
|
+
* and returns only the type identifiers whose backend reports availability.
|
|
220
|
+
* If a backend's `isAvailable()` call throws, that backend is excluded from
|
|
221
|
+
* the result rather than propagating the error.
|
|
222
|
+
*
|
|
223
|
+
* @returns Promise resolving to an array of available backend type identifiers
|
|
224
|
+
* @public
|
|
225
|
+
*/
|
|
226
|
+
static async getAvailableTypes() {
|
|
227
|
+
const entries = Array.from(this.backends.entries());
|
|
228
|
+
const results = await Promise.all(
|
|
229
|
+
entries.map(async ([type, factory]) => {
|
|
230
|
+
try {
|
|
231
|
+
const backend = factory();
|
|
232
|
+
const available = await backend.isAvailable();
|
|
233
|
+
return available ? type : null;
|
|
234
|
+
} catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
})
|
|
238
|
+
);
|
|
239
|
+
return results.filter((type) => type !== null);
|
|
240
|
+
}
|
|
209
241
|
};
|
|
210
242
|
async function execCommand(command, args, options) {
|
|
211
243
|
const result = await execCommandFull(command, args);
|
|
@@ -239,7 +271,7 @@ path5.join(".vaultkeeper", "file");
|
|
|
239
271
|
path5.join(".vaultkeeper", "yubikey");
|
|
240
272
|
function hashExecutable(filePath) {
|
|
241
273
|
return new Promise((resolve, reject) => {
|
|
242
|
-
const hash =
|
|
274
|
+
const hash = crypto4.createHash("sha256");
|
|
243
275
|
const stream = fs4.createReadStream(filePath);
|
|
244
276
|
stream.on("data", (chunk) => {
|
|
245
277
|
hash.update(chunk);
|
|
@@ -539,10 +571,10 @@ var KeyManager = class {
|
|
|
539
571
|
#rotating = false;
|
|
540
572
|
/** Generate a new 32-byte key with a timestamp-based id. */
|
|
541
573
|
generateKey() {
|
|
542
|
-
const randomSuffix =
|
|
574
|
+
const randomSuffix = crypto4.randomBytes(4).toString("hex");
|
|
543
575
|
return {
|
|
544
576
|
id: `k-${String(Date.now())}-${randomSuffix}`,
|
|
545
|
-
key: new Uint8Array(
|
|
577
|
+
key: new Uint8Array(crypto4.randomBytes(32)),
|
|
546
578
|
createdAt: /* @__PURE__ */ new Date()
|
|
547
579
|
};
|
|
548
580
|
}
|
|
@@ -958,6 +990,50 @@ function createSecretAccessor(secretValue) {
|
|
|
958
990
|
return proxy;
|
|
959
991
|
}
|
|
960
992
|
|
|
993
|
+
// src/access/sign-util.ts
|
|
994
|
+
var ALLOWED_ALGORITHMS = /* @__PURE__ */ new Set(["sha256", "sha384", "sha512"]);
|
|
995
|
+
function resolveAlgorithmForKey(key, override) {
|
|
996
|
+
const keyType = key.asymmetricKeyType;
|
|
997
|
+
if (keyType === "ed25519" || keyType === "ed448") {
|
|
998
|
+
return { signAlg: null, label: keyType };
|
|
999
|
+
}
|
|
1000
|
+
const alg = override ?? "sha256";
|
|
1001
|
+
if (!ALLOWED_ALGORITHMS.has(alg)) {
|
|
1002
|
+
throw new VaultError(
|
|
1003
|
+
`Unsupported signing algorithm '${alg}'. Allowed: ${[...ALLOWED_ALGORITHMS].join(", ")}`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
return { signAlg: alg, label: alg };
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
// src/access/delegated-sign.ts
|
|
1010
|
+
function delegatedSign(secretPem, request) {
|
|
1011
|
+
const key = crypto4.createPrivateKey(secretPem);
|
|
1012
|
+
const { signAlg, label } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1013
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1014
|
+
const signature = crypto4.sign(signAlg, data, key);
|
|
1015
|
+
return {
|
|
1016
|
+
signature: signature.toString("base64"),
|
|
1017
|
+
algorithm: label
|
|
1018
|
+
};
|
|
1019
|
+
}
|
|
1020
|
+
function delegatedVerify(request) {
|
|
1021
|
+
let key;
|
|
1022
|
+
try {
|
|
1023
|
+
key = crypto4.createPublicKey(request.publicKey);
|
|
1024
|
+
} catch {
|
|
1025
|
+
return false;
|
|
1026
|
+
}
|
|
1027
|
+
const { signAlg } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1028
|
+
const sig = Buffer.from(request.signature, "base64");
|
|
1029
|
+
try {
|
|
1030
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1031
|
+
return crypto4.verify(signAlg, data, key, sig);
|
|
1032
|
+
} catch {
|
|
1033
|
+
return false;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
961
1037
|
// src/doctor/checks.ts
|
|
962
1038
|
function parseVersion(raw) {
|
|
963
1039
|
const match = /(\d+)\.(\d+)\.(\d+)/.exec(raw);
|
|
@@ -1210,7 +1286,7 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1210
1286
|
}
|
|
1211
1287
|
const now = Math.floor(Date.now() / 1e3);
|
|
1212
1288
|
const claims = {
|
|
1213
|
-
jti:
|
|
1289
|
+
jti: crypto4.randomUUID(),
|
|
1214
1290
|
exp: now + ttlMinutes * 60,
|
|
1215
1291
|
iat: now,
|
|
1216
1292
|
sub: secretName,
|
|
@@ -1315,6 +1391,47 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1315
1391
|
const claims = validateCapabilityToken(token);
|
|
1316
1392
|
return createSecretAccessor(claims.val);
|
|
1317
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Sign data using the private key embedded in a capability token.
|
|
1396
|
+
*
|
|
1397
|
+
* The signing key is extracted from the token's encrypted claims, used
|
|
1398
|
+
* for a single `crypto.sign()` call, and never exposed to the caller.
|
|
1399
|
+
* The algorithm is auto-detected from the key type unless overridden
|
|
1400
|
+
* in the request.
|
|
1401
|
+
*
|
|
1402
|
+
* @param token - A `CapabilityToken` obtained from `authorize()`.
|
|
1403
|
+
* @param request - The data to sign and optional algorithm override.
|
|
1404
|
+
* @returns The base64-encoded signature and algorithm label, together
|
|
1405
|
+
* with the vault metadata (`vaultResponse`).
|
|
1406
|
+
* @throws {VaultError} If `token` is invalid or was not created by this
|
|
1407
|
+
* vault instance.
|
|
1408
|
+
*/
|
|
1409
|
+
async sign(token, request) {
|
|
1410
|
+
const claims = validateCapabilityToken(token);
|
|
1411
|
+
const result = delegatedSign(claims.val, request);
|
|
1412
|
+
await Promise.resolve();
|
|
1413
|
+
return {
|
|
1414
|
+
result,
|
|
1415
|
+
vaultResponse: { keyStatus: "current" }
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
/**
|
|
1419
|
+
* Verify a signature using a public key.
|
|
1420
|
+
*
|
|
1421
|
+
* This is a static method — no VaultKeeper instance, secrets, or
|
|
1422
|
+
* capability tokens are required. It is safe to call from CI or any
|
|
1423
|
+
* context that has access to public key material.
|
|
1424
|
+
*
|
|
1425
|
+
* Never throws. Returns `false` for invalid key material, malformed
|
|
1426
|
+
* signatures, or any verification failure.
|
|
1427
|
+
*
|
|
1428
|
+
* @param request - The data, signature, public key, and optional
|
|
1429
|
+
* algorithm override.
|
|
1430
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
1431
|
+
*/
|
|
1432
|
+
static verify(request) {
|
|
1433
|
+
return delegatedVerify(request);
|
|
1434
|
+
}
|
|
1318
1435
|
/**
|
|
1319
1436
|
* Rotate the current encryption key.
|
|
1320
1437
|
*
|
|
@@ -1431,6 +1548,6 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1431
1548
|
}
|
|
1432
1549
|
};
|
|
1433
1550
|
|
|
1434
|
-
export { AuthorizationDeniedError, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, PluginNotFoundError, RotationInProgressError, SecretNotFoundError, SetupError, TokenExpiredError, TokenRevokedError, UsageLimitExceededError, VaultError, VaultKeeper };
|
|
1551
|
+
export { AuthorizationDeniedError, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, PluginNotFoundError, RotationInProgressError, SecretNotFoundError, SetupError, TokenExpiredError, TokenRevokedError, UsageLimitExceededError, VaultError, VaultKeeper, isListableBackend };
|
|
1435
1552
|
//# sourceMappingURL=index.js.map
|
|
1436
1553
|
//# sourceMappingURL=index.js.map
|