@siglo/crypto 0.0.0-stage → 1.0.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/LICENSE +21 -0
- package/README.md +120 -2
- package/dist/cipher/aes-gcm.d.ts +43 -0
- package/dist/cipher/aes-gcm.d.ts.map +1 -0
- package/dist/cipher/aes-gcm.js +152 -0
- package/dist/cipher/aes-gcm.js.map +1 -0
- package/dist/cipher/decrypt-step.d.ts +13 -0
- package/dist/cipher/decrypt-step.d.ts.map +1 -0
- package/dist/cipher/decrypt-step.js +113 -0
- package/dist/cipher/decrypt-step.js.map +1 -0
- package/dist/cipher/encrypt-step.d.ts +13 -0
- package/dist/cipher/encrypt-step.d.ts.map +1 -0
- package/dist/cipher/encrypt-step.js +84 -0
- package/dist/cipher/encrypt-step.js.map +1 -0
- package/dist/cipher/key-ring.d.ts +24 -0
- package/dist/cipher/key-ring.d.ts.map +1 -0
- package/dist/cipher/key-ring.js +67 -0
- package/dist/cipher/key-ring.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/redaction/mask-step.d.ts +28 -0
- package/dist/redaction/mask-step.d.ts.map +1 -0
- package/dist/redaction/mask-step.js +85 -0
- package/dist/redaction/mask-step.js.map +1 -0
- package/dist/redaction/paths.d.ts +28 -0
- package/dist/redaction/paths.d.ts.map +1 -0
- package/dist/redaction/paths.js +149 -0
- package/dist/redaction/paths.js.map +1 -0
- package/dist/registry.d.ts +14 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +44 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks/dedup.d.ts +24 -0
- package/dist/webhooks/dedup.d.ts.map +1 -0
- package/dist/webhooks/dedup.js +69 -0
- package/dist/webhooks/dedup.js.map +1 -0
- package/dist/webhooks/protocols/base.d.ts +15 -0
- package/dist/webhooks/protocols/base.d.ts.map +1 -0
- package/dist/webhooks/protocols/base.js +42 -0
- package/dist/webhooks/protocols/base.js.map +1 -0
- package/dist/webhooks/protocols/generic-hmac.d.ts +16 -0
- package/dist/webhooks/protocols/generic-hmac.d.ts.map +1 -0
- package/dist/webhooks/protocols/generic-hmac.js +68 -0
- package/dist/webhooks/protocols/generic-hmac.js.map +1 -0
- package/dist/webhooks/protocols/github.d.ts +9 -0
- package/dist/webhooks/protocols/github.d.ts.map +1 -0
- package/dist/webhooks/protocols/github.js +49 -0
- package/dist/webhooks/protocols/github.js.map +1 -0
- package/dist/webhooks/protocols/shopify.d.ts +9 -0
- package/dist/webhooks/protocols/shopify.d.ts.map +1 -0
- package/dist/webhooks/protocols/shopify.js +37 -0
- package/dist/webhooks/protocols/shopify.js.map +1 -0
- package/dist/webhooks/protocols/slack.d.ts +9 -0
- package/dist/webhooks/protocols/slack.d.ts.map +1 -0
- package/dist/webhooks/protocols/slack.js +52 -0
- package/dist/webhooks/protocols/slack.js.map +1 -0
- package/dist/webhooks/protocols/stripe.d.ts +9 -0
- package/dist/webhooks/protocols/stripe.d.ts.map +1 -0
- package/dist/webhooks/protocols/stripe.js +56 -0
- package/dist/webhooks/protocols/stripe.js.map +1 -0
- package/dist/webhooks/protocols/svix.d.ts +9 -0
- package/dist/webhooks/protocols/svix.d.ts.map +1 -0
- package/dist/webhooks/protocols/svix.js +85 -0
- package/dist/webhooks/protocols/svix.js.map +1 -0
- package/dist/webhooks/timing.d.ts +6 -0
- package/dist/webhooks/timing.d.ts.map +1 -0
- package/dist/webhooks/timing.js +25 -0
- package/dist/webhooks/timing.js.map +1 -0
- package/dist/webhooks/verify-step.d.ts +25 -0
- package/dist/webhooks/verify-step.d.ts.map +1 -0
- package/dist/webhooks/verify-step.js +351 -0
- package/dist/webhooks/verify-step.js.map +1 -0
- package/package.json +52 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2017 Jerico de guzman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,121 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @siglo/crypto
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Zero-dependency cryptographic step package for Siglo workflows: timing-safe webhook verification, AEAD envelope field encryption, and context redaction.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Timing-Attack Safe**: Guarantees constant-time buffer comparison via `node:crypto.timingSafeEqual` with strict length guards.
|
|
10
|
+
- **Replay Attack Defense**: Automatic header timestamp parsing and configurable tolerance windows (`toleranceSeconds: 300`).
|
|
11
|
+
- **Zero Serialization Skew**: Enforces verification strictly over raw `Buffer` or unparsed payload strings before JSON parsing.
|
|
12
|
+
- **Pluggable Webhook Strategies**: Built-in presets for Stripe, GitHub, Shopify, Slack, Svix / Standard Webhooks, and generic HMAC, plus support for custom protocols and asymmetric Ed25519/RSA keys.
|
|
13
|
+
- **Envelope Encryption**: Field-level AES-256-GCM encryption with fresh 96-bit (12-byte) IVs per invocation for securing sensitive context across durable checkpoints.
|
|
14
|
+
- **Context Redaction & Masking**: Declarative PII masking (`maskFieldsStep`) with presets for SSNs, credit cards, emails, and custom patterns.
|
|
15
|
+
- **Zero External Dependencies**: Built entirely on Node.js standard libraries (`node:crypto`).
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @siglo/crypto
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Usage Examples
|
|
28
|
+
|
|
29
|
+
### 1. Webhook Signature Verification
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { flow } from '@siglo/core';
|
|
33
|
+
import { verifyWebhookStep } from '@siglo/crypto';
|
|
34
|
+
|
|
35
|
+
interface WebhookContext {
|
|
36
|
+
rawBody: string;
|
|
37
|
+
headers: Record<string, string>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const processWebhook = flow(
|
|
41
|
+
verifyWebhookStep('verifyStripe', {
|
|
42
|
+
provider: 'stripe',
|
|
43
|
+
secret: process.env.STRIPE_WEBHOOK_SECRET!,
|
|
44
|
+
payload: (ctx: WebhookContext) => ctx.rawBody,
|
|
45
|
+
signature: (ctx: WebhookContext) => ctx.headers['stripe-signature'],
|
|
46
|
+
toleranceSeconds: 300,
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Envelope Field Encryption across Durable Checkpoints
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { flow, waitForEvent, Step } from '@siglo/core';
|
|
55
|
+
import { encryptFieldsStep, decryptFieldsStep } from '@siglo/crypto';
|
|
56
|
+
|
|
57
|
+
interface UserContext {
|
|
58
|
+
userId: string;
|
|
59
|
+
ssn: string;
|
|
60
|
+
creditCard: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const sensitiveWorkflow = flow(
|
|
64
|
+
// Encrypt sensitive fields before saving durable checkpoint
|
|
65
|
+
encryptFieldsStep('securePii', {
|
|
66
|
+
fields: ['ssn', 'creditCard'],
|
|
67
|
+
secretKey: process.env.MASTER_KEY!,
|
|
68
|
+
}),
|
|
69
|
+
|
|
70
|
+
// State in checkpoint storage (PostgreSQL/Redis) is encrypted at rest!
|
|
71
|
+
waitForEvent('USER_VERIFIED', { timeout: '24h' }),
|
|
72
|
+
|
|
73
|
+
// Decrypt fields back into plaintext upon workflow resumption
|
|
74
|
+
decryptFieldsStep('unprotectPii', {
|
|
75
|
+
fields: ['ssn', 'creditCard'],
|
|
76
|
+
secretKey: process.env.MASTER_KEY!,
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. Context Redaction / Masking
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { flow } from '@siglo/core';
|
|
85
|
+
import { maskFieldsStep, maskPatterns } from '@siglo/crypto';
|
|
86
|
+
|
|
87
|
+
export const sanitizeWorkflow = flow(
|
|
88
|
+
maskFieldsStep('maskSensitiveData', {
|
|
89
|
+
fields: ['creditCard', 'ssn'],
|
|
90
|
+
maskPattern: maskPatterns.last4,
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 4. Custom Asymmetric Webhook Protocol (Ed25519)
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { verifyWebhookStep, WebhookProtocol } from '@siglo/crypto';
|
|
99
|
+
import crypto from 'node:crypto';
|
|
100
|
+
|
|
101
|
+
export const customEd25519Protocol: WebhookProtocol = {
|
|
102
|
+
name: 'custom-ed25519',
|
|
103
|
+
verify({ secret, rawPayload, headers, signatureHeader, toleranceSeconds = 300 }) {
|
|
104
|
+
const timestamp = Number(headers['x-timestamp']);
|
|
105
|
+
const now = Math.floor(Date.now() / 1000);
|
|
106
|
+
if (Math.abs(now - timestamp) > toleranceSeconds) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const toSign = Buffer.from(`${timestamp}.${rawPayload}`);
|
|
111
|
+
const signature = Buffer.from(signatureHeader, 'base64');
|
|
112
|
+
return crypto.verify(null, toSign, secret, signature);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT © Jerico de Guzman
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { EncryptedEnvelope } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard for EncryptedEnvelope.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isEncryptedEnvelope(val: unknown): val is EncryptedEnvelope;
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a 256-bit (32-byte) key buffer from a string or Buffer.
|
|
8
|
+
* Supports raw 32-byte Buffers, 64-char hex strings, 32-char UTF-8 strings,
|
|
9
|
+
* or derives a 32-byte key via SHA-256 for arbitrary passphrases.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveKey(key: string | Buffer): Buffer;
|
|
12
|
+
/**
|
|
13
|
+
* Derives a context-bound 256-bit subkey from a master key using RFC 5869 HKDF.
|
|
14
|
+
* Isolates cryptographic keyspaces per tenant, workflow run, or checkpoint.
|
|
15
|
+
*/
|
|
16
|
+
export declare function deriveSubkey(masterKey: string | Buffer, contextInfo: string | Buffer, salt?: string | Buffer): Buffer;
|
|
17
|
+
/** NIST SP 800-38D recommended maximum threshold for 96-bit random IVs (2^24) */
|
|
18
|
+
export declare const NIST_RECOMMENDED_INVOCATION_CEILING = 16777216;
|
|
19
|
+
export declare function getKeyInvocationCount(key: string | Buffer): number;
|
|
20
|
+
export declare function resetKeyInvocationCounters(): void;
|
|
21
|
+
export interface EncryptOptions {
|
|
22
|
+
kid?: string;
|
|
23
|
+
aad?: string | Buffer;
|
|
24
|
+
deriveKeyContext?: string | Buffer;
|
|
25
|
+
v?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface DecryptOptions {
|
|
28
|
+
aad?: string | Buffer;
|
|
29
|
+
deriveKeyContext?: string | Buffer;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Encrypts arbitrary data using AES-256-GCM envelope encryption.
|
|
33
|
+
* Generates a cryptographically secure 96-bit (12-byte) IV for each invocation.
|
|
34
|
+
* Supports AAD (Additional Authenticated Data) and context-derived subkeys.
|
|
35
|
+
*/
|
|
36
|
+
export declare function encryptAESGCM(data: unknown, key: string | Buffer, options?: EncryptOptions): EncryptedEnvelope;
|
|
37
|
+
/**
|
|
38
|
+
* Decrypts an AES-256-GCM envelope and verifies authentication tag integrity.
|
|
39
|
+
* Supports AAD verification and context-derived subkey reconstruction.
|
|
40
|
+
* Throws if the auth tag, ciphertext, or AAD was tampered with.
|
|
41
|
+
*/
|
|
42
|
+
export declare function decryptAESGCM(envelope: EncryptedEnvelope, key: string | Buffer, options?: DecryptOptions): any;
|
|
43
|
+
//# sourceMappingURL=aes-gcm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aes-gcm.d.ts","sourceRoot":"","sources":["../../src/cipher/aes-gcm.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB,CAS1E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAoBvD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,WAAW,EAAE,MAAM,GAAG,MAAM,EAC5B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GACrB,MAAM,CAOR;AAKD,iFAAiF;AACjF,eAAO,MAAM,mCAAmC,WAAW,CAAC;AAE5D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGlE;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAgBD,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACnC,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,OAAO,CAAC,EAAE,cAAc,GACvB,iBAAiB,CAqCnB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,OAAO,CAAC,EAAE,cAAc,GACvB,GAAG,CAkCL"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NIST_RECOMMENDED_INVOCATION_CEILING = void 0;
|
|
7
|
+
exports.isEncryptedEnvelope = isEncryptedEnvelope;
|
|
8
|
+
exports.resolveKey = resolveKey;
|
|
9
|
+
exports.deriveSubkey = deriveSubkey;
|
|
10
|
+
exports.getKeyInvocationCount = getKeyInvocationCount;
|
|
11
|
+
exports.resetKeyInvocationCounters = resetKeyInvocationCounters;
|
|
12
|
+
exports.encryptAESGCM = encryptAESGCM;
|
|
13
|
+
exports.decryptAESGCM = decryptAESGCM;
|
|
14
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
15
|
+
/**
|
|
16
|
+
* Type guard for EncryptedEnvelope.
|
|
17
|
+
*/
|
|
18
|
+
function isEncryptedEnvelope(val) {
|
|
19
|
+
return (typeof val === 'object' &&
|
|
20
|
+
val !== null &&
|
|
21
|
+
val.__sigloCipher === 'aes-256-gcm' &&
|
|
22
|
+
typeof val.iv === 'string' &&
|
|
23
|
+
typeof val.tag === 'string' &&
|
|
24
|
+
typeof val.data === 'string');
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolves a 256-bit (32-byte) key buffer from a string or Buffer.
|
|
28
|
+
* Supports raw 32-byte Buffers, 64-char hex strings, 32-char UTF-8 strings,
|
|
29
|
+
* or derives a 32-byte key via SHA-256 for arbitrary passphrases.
|
|
30
|
+
*/
|
|
31
|
+
function resolveKey(key) {
|
|
32
|
+
if (Buffer.isBuffer(key)) {
|
|
33
|
+
if (key.length === 32) {
|
|
34
|
+
return key;
|
|
35
|
+
}
|
|
36
|
+
return node_crypto_1.default.createHash('sha256').update(key).digest();
|
|
37
|
+
}
|
|
38
|
+
if (typeof key === 'string') {
|
|
39
|
+
if (key.length === 64 && /^[0-9a-fA-F]{64}$/.test(key)) {
|
|
40
|
+
return Buffer.from(key, 'hex');
|
|
41
|
+
}
|
|
42
|
+
const utf8Buf = Buffer.from(key, 'utf8');
|
|
43
|
+
if (utf8Buf.length === 32) {
|
|
44
|
+
return utf8Buf;
|
|
45
|
+
}
|
|
46
|
+
return node_crypto_1.default.createHash('sha256').update(key).digest();
|
|
47
|
+
}
|
|
48
|
+
throw new TypeError('Secret key must be a string or Buffer');
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Derives a context-bound 256-bit subkey from a master key using RFC 5869 HKDF.
|
|
52
|
+
* Isolates cryptographic keyspaces per tenant, workflow run, or checkpoint.
|
|
53
|
+
*/
|
|
54
|
+
function deriveSubkey(masterKey, contextInfo, salt) {
|
|
55
|
+
const resolvedMaster = resolveKey(masterKey);
|
|
56
|
+
const resolvedSalt = salt
|
|
57
|
+
? (Buffer.isBuffer(salt) ? salt : Buffer.from(salt))
|
|
58
|
+
: Buffer.alloc(32, 0);
|
|
59
|
+
const info = Buffer.isBuffer(contextInfo) ? contextInfo : Buffer.from(contextInfo);
|
|
60
|
+
return Buffer.from(node_crypto_1.default.hkdfSync('sha256', resolvedMaster, resolvedSalt, info, 32));
|
|
61
|
+
}
|
|
62
|
+
/** Key invocation tracking per key hash to warn/guard against NIST SP 800-38D limits */
|
|
63
|
+
const keyUsageCounts = new Map();
|
|
64
|
+
/** NIST SP 800-38D recommended maximum threshold for 96-bit random IVs (2^24) */
|
|
65
|
+
exports.NIST_RECOMMENDED_INVOCATION_CEILING = 16777216;
|
|
66
|
+
function getKeyInvocationCount(key) {
|
|
67
|
+
const hash = node_crypto_1.default.createHash('sha256').update(resolveKey(key)).digest('hex');
|
|
68
|
+
return keyUsageCounts.get(hash) ?? 0;
|
|
69
|
+
}
|
|
70
|
+
function resetKeyInvocationCounters() {
|
|
71
|
+
keyUsageCounts.clear();
|
|
72
|
+
}
|
|
73
|
+
function recordKeyUsage(key) {
|
|
74
|
+
const hash = node_crypto_1.default.createHash('sha256').update(key).digest('hex');
|
|
75
|
+
const current = (keyUsageCounts.get(hash) ?? 0) + 1;
|
|
76
|
+
keyUsageCounts.set(hash, current);
|
|
77
|
+
if (current === exports.NIST_RECOMMENDED_INVOCATION_CEILING) {
|
|
78
|
+
if (typeof process !== 'undefined' && process.emitWarning) {
|
|
79
|
+
process.emitWarning(`AES-GCM key usage for key fingerprint '${hash.slice(0, 8)}' reached ${exports.NIST_RECOMMENDED_INVOCATION_CEILING} invocations. Key rotation recommended per NIST SP 800-38D.`, 'SecurityWarning');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Encrypts arbitrary data using AES-256-GCM envelope encryption.
|
|
85
|
+
* Generates a cryptographically secure 96-bit (12-byte) IV for each invocation.
|
|
86
|
+
* Supports AAD (Additional Authenticated Data) and context-derived subkeys.
|
|
87
|
+
*/
|
|
88
|
+
function encryptAESGCM(data, key, options) {
|
|
89
|
+
let resolvedKey = resolveKey(key);
|
|
90
|
+
if (options?.deriveKeyContext) {
|
|
91
|
+
resolvedKey = deriveSubkey(resolvedKey, options.deriveKeyContext);
|
|
92
|
+
}
|
|
93
|
+
recordKeyUsage(resolvedKey);
|
|
94
|
+
const iv = node_crypto_1.default.randomBytes(12);
|
|
95
|
+
const plaintext = JSON.stringify(data);
|
|
96
|
+
const cipher = node_crypto_1.default.createCipheriv('aes-256-gcm', resolvedKey, iv);
|
|
97
|
+
if (options?.aad) {
|
|
98
|
+
const aadBuf = Buffer.isBuffer(options.aad) ? options.aad : Buffer.from(options.aad);
|
|
99
|
+
cipher.setAAD(aadBuf);
|
|
100
|
+
}
|
|
101
|
+
const ciphertext = Buffer.concat([
|
|
102
|
+
cipher.update(plaintext, 'utf8'),
|
|
103
|
+
cipher.final()
|
|
104
|
+
]);
|
|
105
|
+
const tag = cipher.getAuthTag();
|
|
106
|
+
const envelope = {
|
|
107
|
+
__sigloCipher: 'aes-256-gcm',
|
|
108
|
+
v: options?.v ?? 1,
|
|
109
|
+
iv: iv.toString('hex'),
|
|
110
|
+
tag: tag.toString('hex'),
|
|
111
|
+
data: ciphertext.toString('hex')
|
|
112
|
+
};
|
|
113
|
+
if (options?.kid) {
|
|
114
|
+
envelope.kid = options.kid;
|
|
115
|
+
}
|
|
116
|
+
return envelope;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Decrypts an AES-256-GCM envelope and verifies authentication tag integrity.
|
|
120
|
+
* Supports AAD verification and context-derived subkey reconstruction.
|
|
121
|
+
* Throws if the auth tag, ciphertext, or AAD was tampered with.
|
|
122
|
+
*/
|
|
123
|
+
function decryptAESGCM(envelope, key, options) {
|
|
124
|
+
if (!isEncryptedEnvelope(envelope)) {
|
|
125
|
+
throw new TypeError('Invalid encrypted envelope structure');
|
|
126
|
+
}
|
|
127
|
+
let resolvedKey = resolveKey(key);
|
|
128
|
+
if (options?.deriveKeyContext) {
|
|
129
|
+
resolvedKey = deriveSubkey(resolvedKey, options.deriveKeyContext);
|
|
130
|
+
}
|
|
131
|
+
const iv = Buffer.from(envelope.iv, 'hex');
|
|
132
|
+
const tag = Buffer.from(envelope.tag, 'hex');
|
|
133
|
+
const ciphertext = Buffer.from(envelope.data, 'hex');
|
|
134
|
+
const decipher = node_crypto_1.default.createDecipheriv('aes-256-gcm', resolvedKey, iv);
|
|
135
|
+
if (options?.aad) {
|
|
136
|
+
const aadBuf = Buffer.isBuffer(options.aad) ? options.aad : Buffer.from(options.aad);
|
|
137
|
+
decipher.setAAD(aadBuf);
|
|
138
|
+
}
|
|
139
|
+
decipher.setAuthTag(tag);
|
|
140
|
+
const decrypted = Buffer.concat([
|
|
141
|
+
decipher.update(ciphertext),
|
|
142
|
+
decipher.final()
|
|
143
|
+
]);
|
|
144
|
+
const plaintextStr = decrypted.toString('utf8');
|
|
145
|
+
try {
|
|
146
|
+
return JSON.parse(plaintextStr);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return plaintextStr;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=aes-gcm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../src/cipher/aes-gcm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Step, ExecutionOptions } from '@siglo/core';
|
|
2
|
+
import { FieldCipherOptions } from '../types';
|
|
3
|
+
export declare class DecryptFieldsStep<TInput = any, TName extends string = string> extends Step<TInput, TInput, TName> {
|
|
4
|
+
constructor(name: TName, options: FieldCipherOptions<TInput>);
|
|
5
|
+
execute(param?: TInput, options?: ExecutionOptions): Promise<TInput>;
|
|
6
|
+
run(param?: TInput, options?: ExecutionOptions): Promise<TInput>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a step that decrypts encrypted context envelopes in-place back to their plaintext values.
|
|
10
|
+
* Supports dot-notation paths, KeyRing rotation, AAD verification, and lazy checkpoint re-key flags.
|
|
11
|
+
*/
|
|
12
|
+
export declare function decryptFieldsStep<const TName extends string, TInput>(name: TName, options: FieldCipherOptions<TInput>): DecryptFieldsStep<TInput, TName>;
|
|
13
|
+
//# sourceMappingURL=decrypt-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decrypt-step.d.ts","sourceRoot":"","sources":["../../src/cipher/decrypt-step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAW,MAAM,UAAU,CAAC;AAkBvD,qBAAa,iBAAiB,CAAC,MAAM,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,CACxE,SAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;gBAEvB,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC;IAgGnD,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpE,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAG1E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,EAClE,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAClC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAElC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DecryptFieldsStep = void 0;
|
|
4
|
+
exports.decryptFieldsStep = decryptFieldsStep;
|
|
5
|
+
const core_1 = require("@siglo/core");
|
|
6
|
+
const aes_gcm_1 = require("./aes-gcm");
|
|
7
|
+
const key_ring_1 = require("./key-ring");
|
|
8
|
+
const paths_1 = require("../redaction/paths");
|
|
9
|
+
function sanitizeStepInput(param) {
|
|
10
|
+
if (!param || typeof param !== 'object' || Array.isArray(param)) {
|
|
11
|
+
return param;
|
|
12
|
+
}
|
|
13
|
+
const clean = {};
|
|
14
|
+
for (const [key, val] of Object.entries(param)) {
|
|
15
|
+
if (key !== '$steps' && key !== '$history' && key !== '$stackId') {
|
|
16
|
+
clean[key] = val;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return clean;
|
|
20
|
+
}
|
|
21
|
+
class DecryptFieldsStep extends core_1.Step {
|
|
22
|
+
constructor(name, options) {
|
|
23
|
+
const action = async (ctx) => {
|
|
24
|
+
// 1. Resolve key or KeyRing
|
|
25
|
+
let keyOrRing;
|
|
26
|
+
if (options.keyRing) {
|
|
27
|
+
keyOrRing = options.keyRing;
|
|
28
|
+
}
|
|
29
|
+
else if (typeof options.secretKey === 'function') {
|
|
30
|
+
keyOrRing = await options.secretKey(ctx);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
keyOrRing = options.secretKey;
|
|
34
|
+
}
|
|
35
|
+
if (!keyOrRing) {
|
|
36
|
+
throw new core_1.ValidationException([{ field: 'secretKey', message: 'Secret key or KeyRing is required for decryption' }], { stepName: name, phase: 'action', retryable: false });
|
|
37
|
+
}
|
|
38
|
+
// 2. Resolve optional AAD and deriveKeyContext
|
|
39
|
+
const resolvedAad = typeof options.aad === 'function' ? options.aad(ctx) : options.aad;
|
|
40
|
+
const resolvedDeriveCtx = typeof options.deriveKeyContext === 'function'
|
|
41
|
+
? options.deriveKeyContext(ctx)
|
|
42
|
+
: options.deriveKeyContext;
|
|
43
|
+
let hasRekeyNeeded = false;
|
|
44
|
+
// 3. Decrypt fields using structural sharing
|
|
45
|
+
const result = (0, paths_1.transformFields)(ctx, options.fields, (val, concretePath) => {
|
|
46
|
+
if (!(0, aes_gcm_1.isEncryptedEnvelope)(val)) {
|
|
47
|
+
return val;
|
|
48
|
+
}
|
|
49
|
+
const fieldName = concretePath.join('.');
|
|
50
|
+
// Resolve key for this specific envelope
|
|
51
|
+
let keyToUse;
|
|
52
|
+
let activeKid;
|
|
53
|
+
if ((0, key_ring_1.isKeyRing)(keyOrRing)) {
|
|
54
|
+
const active = keyOrRing.getActiveKey();
|
|
55
|
+
activeKid = active instanceof Promise ? undefined : active.kid;
|
|
56
|
+
if (val.kid) {
|
|
57
|
+
keyToUse = keyOrRing.getKey(val.kid);
|
|
58
|
+
if (!keyToUse) {
|
|
59
|
+
throw new core_1.ValidationException([{ field: fieldName, message: `Failed to decrypt field '${fieldName}': key ID '${val.kid}' not found in KeyRing` }], { stepName: name, phase: 'action', retryable: false });
|
|
60
|
+
}
|
|
61
|
+
if (activeKid && val.kid !== activeKid) {
|
|
62
|
+
hasRekeyNeeded = true;
|
|
63
|
+
if (options.onNeedsRekey) {
|
|
64
|
+
options.onNeedsRekey(ctx, fieldName, val.kid, activeKid);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Legacy envelope without kid: try active key
|
|
70
|
+
const activeRes = active instanceof Promise ? undefined : active;
|
|
71
|
+
keyToUse = activeRes?.key;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
keyToUse = keyOrRing;
|
|
76
|
+
}
|
|
77
|
+
if (!keyToUse) {
|
|
78
|
+
throw new core_1.ValidationException([{ field: fieldName, message: `Failed to resolve decryption key for field '${fieldName}'` }], { stepName: name, phase: 'action', retryable: false });
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
return (0, aes_gcm_1.decryptAESGCM)(val, keyToUse, {
|
|
82
|
+
aad: resolvedAad,
|
|
83
|
+
deriveKeyContext: resolvedDeriveCtx
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
throw new core_1.ValidationException([{ field: fieldName, message: `Failed to decrypt field '${fieldName}': authentication tag verification failed` }], { stepName: name, phase: 'action', retryable: false, cause: err });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
if (hasRekeyNeeded && !options.onNeedsRekey && typeof result === 'object' && result !== null) {
|
|
91
|
+
result.$needsRekey = true;
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
};
|
|
95
|
+
super(name, action);
|
|
96
|
+
}
|
|
97
|
+
execute(param, options) {
|
|
98
|
+
const cleanParam = param ? sanitizeStepInput(param) : param;
|
|
99
|
+
return super.execute(cleanParam, { pojo: true, ...options });
|
|
100
|
+
}
|
|
101
|
+
run(param, options) {
|
|
102
|
+
return this.execute(param, options);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.DecryptFieldsStep = DecryptFieldsStep;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a step that decrypts encrypted context envelopes in-place back to their plaintext values.
|
|
108
|
+
* Supports dot-notation paths, KeyRing rotation, AAD verification, and lazy checkpoint re-key flags.
|
|
109
|
+
*/
|
|
110
|
+
function decryptFieldsStep(name, options) {
|
|
111
|
+
return new DecryptFieldsStep(name, options);
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=decrypt-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decrypt-step.js","sourceRoot":"","sources":["../../src/cipher/decrypt-step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Step, ExecutionOptions } from '@siglo/core';
|
|
2
|
+
import { FieldCipherOptions } from '../types';
|
|
3
|
+
export declare class EncryptFieldsStep<TInput = any, TName extends string = string> extends Step<TInput, TInput, TName> {
|
|
4
|
+
constructor(name: TName, options: FieldCipherOptions<TInput>);
|
|
5
|
+
execute(param?: TInput, options?: ExecutionOptions): Promise<TInput>;
|
|
6
|
+
run(param?: TInput, options?: ExecutionOptions): Promise<TInput>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a step that encrypts specified context fields in-place using AES-256-GCM envelope encryption.
|
|
10
|
+
* Supports dot-notation paths, wildcards, KeyRing rotation, AAD, and HKDF key derivation.
|
|
11
|
+
*/
|
|
12
|
+
export declare function encryptFieldsStep<const TName extends string, TInput>(name: TName, options: FieldCipherOptions<TInput>): EncryptFieldsStep<TInput, TName>;
|
|
13
|
+
//# sourceMappingURL=encrypt-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypt-step.d.ts","sourceRoot":"","sources":["../../src/cipher/encrypt-step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAuB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAW,MAAM,UAAU,CAAC;AAkBvD,qBAAa,iBAAiB,CAAC,MAAM,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,CACxE,SAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;gBAEvB,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC;IAsDnD,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpE,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;CAG1E;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,EAClE,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,kBAAkB,CAAC,MAAM,CAAC,GAClC,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAElC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EncryptFieldsStep = void 0;
|
|
4
|
+
exports.encryptFieldsStep = encryptFieldsStep;
|
|
5
|
+
const core_1 = require("@siglo/core");
|
|
6
|
+
const aes_gcm_1 = require("./aes-gcm");
|
|
7
|
+
const key_ring_1 = require("./key-ring");
|
|
8
|
+
const paths_1 = require("../redaction/paths");
|
|
9
|
+
function sanitizeStepInput(param) {
|
|
10
|
+
if (!param || typeof param !== 'object' || Array.isArray(param)) {
|
|
11
|
+
return param;
|
|
12
|
+
}
|
|
13
|
+
const clean = {};
|
|
14
|
+
for (const [key, val] of Object.entries(param)) {
|
|
15
|
+
if (key !== '$steps' && key !== '$history' && key !== '$stackId') {
|
|
16
|
+
clean[key] = val;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return clean;
|
|
20
|
+
}
|
|
21
|
+
class EncryptFieldsStep extends core_1.Step {
|
|
22
|
+
constructor(name, options) {
|
|
23
|
+
const action = async (ctx) => {
|
|
24
|
+
// 1. Resolve key or KeyRing
|
|
25
|
+
let keyOrRing;
|
|
26
|
+
if (options.keyRing) {
|
|
27
|
+
keyOrRing = options.keyRing;
|
|
28
|
+
}
|
|
29
|
+
else if (typeof options.secretKey === 'function') {
|
|
30
|
+
keyOrRing = await options.secretKey(ctx);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
keyOrRing = options.secretKey;
|
|
34
|
+
}
|
|
35
|
+
if (!keyOrRing) {
|
|
36
|
+
throw new core_1.ValidationException([{ field: 'secretKey', message: 'Secret key or KeyRing is required for encryption' }], { stepName: name, phase: 'action', retryable: false });
|
|
37
|
+
}
|
|
38
|
+
let activeKey;
|
|
39
|
+
let activeKid;
|
|
40
|
+
if ((0, key_ring_1.isKeyRing)(keyOrRing)) {
|
|
41
|
+
const active = await keyOrRing.getActiveKey();
|
|
42
|
+
activeKey = active.key;
|
|
43
|
+
activeKid = active.kid;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
activeKey = keyOrRing;
|
|
47
|
+
}
|
|
48
|
+
// 2. Resolve optional AAD and deriveKeyContext
|
|
49
|
+
const resolvedAad = typeof options.aad === 'function' ? options.aad(ctx) : options.aad;
|
|
50
|
+
const resolvedDeriveCtx = typeof options.deriveKeyContext === 'function'
|
|
51
|
+
? options.deriveKeyContext(ctx)
|
|
52
|
+
: options.deriveKeyContext;
|
|
53
|
+
// 3. Encrypt target fields using structural sharing
|
|
54
|
+
const result = (0, paths_1.transformFields)(ctx, options.fields, (val) => {
|
|
55
|
+
if (val !== undefined && val !== null && !(0, aes_gcm_1.isEncryptedEnvelope)(val)) {
|
|
56
|
+
return (0, aes_gcm_1.encryptAESGCM)(val, activeKey, {
|
|
57
|
+
kid: activeKid,
|
|
58
|
+
aad: resolvedAad,
|
|
59
|
+
deriveKeyContext: resolvedDeriveCtx
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return val;
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
};
|
|
66
|
+
super(name, action);
|
|
67
|
+
}
|
|
68
|
+
execute(param, options) {
|
|
69
|
+
const cleanParam = param ? sanitizeStepInput(param) : param;
|
|
70
|
+
return super.execute(cleanParam, { pojo: true, ...options });
|
|
71
|
+
}
|
|
72
|
+
run(param, options) {
|
|
73
|
+
return this.execute(param, options);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.EncryptFieldsStep = EncryptFieldsStep;
|
|
77
|
+
/**
|
|
78
|
+
* Creates a step that encrypts specified context fields in-place using AES-256-GCM envelope encryption.
|
|
79
|
+
* Supports dot-notation paths, wildcards, KeyRing rotation, AAD, and HKDF key derivation.
|
|
80
|
+
*/
|
|
81
|
+
function encryptFieldsStep(name, options) {
|
|
82
|
+
return new EncryptFieldsStep(name, options);
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=encrypt-step.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypt-step.js","sourceRoot":"","sources":["../../src/cipher/encrypt-step.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { KeyRing, KeyRingKey } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if an object satisfies the KeyRing interface.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isKeyRing(val: unknown): val is KeyRing;
|
|
6
|
+
/**
|
|
7
|
+
* In-memory multi-key provider supporting active key generation and historical key retrieval.
|
|
8
|
+
*/
|
|
9
|
+
export declare class StaticKeyRing implements KeyRing {
|
|
10
|
+
private activeKeyId;
|
|
11
|
+
private keys;
|
|
12
|
+
constructor(activeKeyId: string, keys: Record<string, string | Buffer> | Map<string, string | Buffer>);
|
|
13
|
+
getActiveKey(): KeyRingKey;
|
|
14
|
+
getKey(kid: string): string | Buffer | null;
|
|
15
|
+
/**
|
|
16
|
+
* Adds or rotates a key in the ring.
|
|
17
|
+
*/
|
|
18
|
+
addKey(kid: string, key: string | Buffer, makeActive?: boolean): void;
|
|
19
|
+
/**
|
|
20
|
+
* Sets the active key ID for subsequent encryption operations.
|
|
21
|
+
*/
|
|
22
|
+
setActiveKey(kid: string): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=key-ring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-ring.d.ts","sourceRoot":"","sources":["../../src/cipher/key-ring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE/C;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CAOtD;AAED;;GAEG;AACH,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,IAAI,CAA2C;gBAGrD,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IAetE,YAAY,IAAI,UAAU;IAW1B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;IAI3C;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,GAAE,OAAe,GAAG,IAAI;IAO5E;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAMhC"}
|