mask-privacy 4.0.0 → 4.2.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.d.mts +37 -31
- package/dist/index.d.ts +37 -31
- package/dist/index.js +794 -370
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +767 -342
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/config.ts +5 -0
- package/src/core/crypto.ts +171 -87
- package/src/core/exceptions.ts +25 -0
- package/src/core/ff1.ts +196 -0
- package/src/core/fpe.ts +97 -175
- package/src/core/fpe_utils.ts +57 -11
- package/src/core/key_provider.ts +80 -0
- package/src/core/vault.ts +152 -78
- package/src/telemetry/audit_logger.ts +136 -16
- package/tests/bijective_fpe.test.ts +16 -12
- package/tests/fpe.test.ts +17 -8
- package/tests/security_hardening.test.ts +117 -0
- package/tests/vault.test.ts +67 -0
- package/tests/vault_backends.test.ts +7 -7
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/** Interface every vault backend must implement. */
|
|
2
2
|
declare abstract class BaseVault {
|
|
3
|
-
/** Persist a token → plaintext mapping with a TTL
|
|
4
|
-
abstract store(token: string, plaintext: string, ttlSeconds: number, ptHash?: string | null): Promise<void>;
|
|
3
|
+
/** Persist a token → encrypted plaintext mapping with a TTL and optional compliance metadata. */
|
|
4
|
+
abstract store(token: string, plaintext: string, ttlSeconds: number, ptHash?: string | null, metadata?: Record<string, string> | null): Promise<void>;
|
|
5
5
|
/** Return the existing unexpired token for a given plaintext hash, or null. */
|
|
6
6
|
abstract getTokenByPlaintextHash(ptHash: string): Promise<string | null>;
|
|
7
7
|
/** Return the plaintext for token, or null if missing/expired. */
|
|
8
8
|
abstract retrieve(token: string): Promise<string | null>;
|
|
9
|
+
/** Return the plaintext hash stored for this token (used for collision detection), or null. */
|
|
10
|
+
abstract getPtHashForToken(token: string): Promise<string | null>;
|
|
9
11
|
/** Delete a token and its reverse mapping. */
|
|
10
12
|
abstract delete(token: string): Promise<void>;
|
|
11
13
|
}
|
|
@@ -15,6 +17,7 @@ type EncodeOptions = {
|
|
|
15
17
|
searchBuckets?: ('year' | 'month' | 'day' | 'numeric')[];
|
|
16
18
|
searchBucketSize?: number;
|
|
17
19
|
entityType?: string;
|
|
20
|
+
metadata?: Record<string, string> | null;
|
|
18
21
|
};
|
|
19
22
|
/**
|
|
20
23
|
* Tokenise rawText, encrypt it, store in vault, return the FPE token.
|
|
@@ -41,18 +44,11 @@ declare const adetokenizeText: typeof detokenizeText;
|
|
|
41
44
|
declare function looksLikeToken(value: string | any): boolean;
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* Generates structurally valid, **deterministic** tokens that preserve the
|
|
47
|
-
* format of the original data type so downstream tools, schemas, and
|
|
48
|
-
* validators continue to work without modification.
|
|
47
|
+
* Deterministic Pseudonymization (DP) token generation using NIST SP 800-38G FF1.
|
|
49
48
|
*/
|
|
50
|
-
/** Clear the cached master key. Useful in tests. */
|
|
51
49
|
declare function resetMasterKey(): void;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
|
-
declare function generateFPEToken(rawText: string, entityType?: string): Promise<string>;
|
|
50
|
+
declare function generateDPToken(rawText: string, entityType?: string): Promise<string>;
|
|
51
|
+
declare const generateFPEToken: typeof generateDPToken;
|
|
56
52
|
|
|
57
53
|
/**
|
|
58
54
|
* Span Resolution Engine — Sweep-Line Overlap Resolver (TypeScript).
|
|
@@ -184,44 +180,43 @@ declare class MaskSecurityError extends MaskError {
|
|
|
184
180
|
/**
|
|
185
181
|
* Core cryptography engine for Mask SDK.
|
|
186
182
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
183
|
+
* Supports a JSON-based Keyring for transparent key rotation:
|
|
184
|
+
* MASK_KEYRING='{"v1":"oldkey...","v2":"newkey..."}'
|
|
185
|
+
* The *last* key in the JSON object is the active encryption key.
|
|
186
|
+
* All keys in the keyring are available for decryption (zero-downtime rotation).
|
|
190
187
|
*
|
|
191
|
-
*
|
|
192
|
-
* Includes a compatibility layer to decrypt legacy Fernet-format tokens.
|
|
188
|
+
* Legacy single-key mode (MASK_ENCRYPTION_KEY) is fully mapped to key ID "default".
|
|
193
189
|
*
|
|
194
|
-
*
|
|
190
|
+
* Ciphertext envelope format: aes:v2:{keyId}:{base64(iv+authTag+ciphertext)}
|
|
191
|
+
*
|
|
192
|
+
* Uses AES-256-GCM via native Node.js crypto and Argon2id for key derivation.
|
|
195
193
|
*/
|
|
196
194
|
declare class CryptoEngine {
|
|
197
195
|
private static _instance;
|
|
198
|
-
private
|
|
196
|
+
private _keyring;
|
|
197
|
+
private _activeKeyId;
|
|
199
198
|
private _indexSecret;
|
|
200
199
|
private constructor();
|
|
201
200
|
/**
|
|
202
201
|
* Return the singleton instance, initialising it if necessary.
|
|
203
|
-
*
|
|
202
|
+
* Async because Argon2id key derivation is async.
|
|
204
203
|
*/
|
|
205
204
|
static getInstanceAsync(): Promise<CryptoEngine>;
|
|
206
205
|
/** Legacy synchronous accessor — will throw if not already initialised. */
|
|
207
206
|
static getInstance(): CryptoEngine;
|
|
208
|
-
/** Clear the singleton
|
|
207
|
+
/** Clear the singleton (useful for key rotation / tests). */
|
|
209
208
|
static reset(): void;
|
|
209
|
+
private _deriveAesKey;
|
|
210
210
|
private _init;
|
|
211
211
|
/** Return the secret used for HMAC-based blind indexing. */
|
|
212
212
|
getIndexSecret(): Promise<Buffer>;
|
|
213
|
+
/** Encrypt plaintext using the active keyring key.
|
|
214
|
+
* Envelope format: aes:v2:{keyId}:{base64(iv+authTag+ciphertext)}
|
|
215
|
+
*/
|
|
213
216
|
encrypt(plaintext: string): string;
|
|
217
|
+
/** Decrypt ciphertext. Supports all historical envelope formats. */
|
|
214
218
|
decrypt(ciphertext: string): string;
|
|
215
|
-
/** Decrypt an AES-256-GCM token (base64 encoded). */
|
|
216
219
|
private _decryptAesGcm;
|
|
217
|
-
/**
|
|
218
|
-
* Attempt to decrypt a legacy Fernet-format token.
|
|
219
|
-
*
|
|
220
|
-
* Fernet format: Version (1) || Timestamp (8) || IV (16) || Ciphertext (var) || HMAC (32)
|
|
221
|
-
* All base64url-encoded.
|
|
222
|
-
*
|
|
223
|
-
* We try to use the `fernet` npm package if available, otherwise throw.
|
|
224
|
-
*/
|
|
225
220
|
private _decryptLegacyFernet;
|
|
226
221
|
}
|
|
227
222
|
|
|
@@ -236,13 +231,24 @@ declare class AuditLogger {
|
|
|
236
231
|
private _strictMode;
|
|
237
232
|
private _bufferFullWarned;
|
|
238
233
|
private _shutdownRegistered;
|
|
234
|
+
private _signingKey;
|
|
235
|
+
private _prevSig;
|
|
236
|
+
private _instanceId;
|
|
239
237
|
private constructor();
|
|
240
238
|
static getInstance(): AuditLogger;
|
|
239
|
+
private _getOverflowPath;
|
|
240
|
+
private _writeOverflow;
|
|
241
|
+
private _consumeOverflow;
|
|
241
242
|
log(action: string, token: string, dataType?: string, agent?: string, tool?: string, extra?: Record<string, any>): void;
|
|
242
243
|
start(): void;
|
|
243
244
|
stop(): Promise<void>;
|
|
244
245
|
private _flush;
|
|
245
|
-
/** Synchronous flush for use in signal handlers where async is unreliable.
|
|
246
|
+
/** Synchronous flush for use in signal handlers where async is unreliable.
|
|
247
|
+
*
|
|
248
|
+
* Computes HMAC signatures to maintain chain integrity and writes to the
|
|
249
|
+
* secure ndjson audit file (MASK_SECURE_AUDIT_LOG_DIR) if configured,
|
|
250
|
+
* ensuring SOC 2 tamper-evidence guarantees hold through process shutdown.
|
|
251
|
+
*/
|
|
246
252
|
private _flushSync;
|
|
247
253
|
}
|
|
248
254
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/** Interface every vault backend must implement. */
|
|
2
2
|
declare abstract class BaseVault {
|
|
3
|
-
/** Persist a token → plaintext mapping with a TTL
|
|
4
|
-
abstract store(token: string, plaintext: string, ttlSeconds: number, ptHash?: string | null): Promise<void>;
|
|
3
|
+
/** Persist a token → encrypted plaintext mapping with a TTL and optional compliance metadata. */
|
|
4
|
+
abstract store(token: string, plaintext: string, ttlSeconds: number, ptHash?: string | null, metadata?: Record<string, string> | null): Promise<void>;
|
|
5
5
|
/** Return the existing unexpired token for a given plaintext hash, or null. */
|
|
6
6
|
abstract getTokenByPlaintextHash(ptHash: string): Promise<string | null>;
|
|
7
7
|
/** Return the plaintext for token, or null if missing/expired. */
|
|
8
8
|
abstract retrieve(token: string): Promise<string | null>;
|
|
9
|
+
/** Return the plaintext hash stored for this token (used for collision detection), or null. */
|
|
10
|
+
abstract getPtHashForToken(token: string): Promise<string | null>;
|
|
9
11
|
/** Delete a token and its reverse mapping. */
|
|
10
12
|
abstract delete(token: string): Promise<void>;
|
|
11
13
|
}
|
|
@@ -15,6 +17,7 @@ type EncodeOptions = {
|
|
|
15
17
|
searchBuckets?: ('year' | 'month' | 'day' | 'numeric')[];
|
|
16
18
|
searchBucketSize?: number;
|
|
17
19
|
entityType?: string;
|
|
20
|
+
metadata?: Record<string, string> | null;
|
|
18
21
|
};
|
|
19
22
|
/**
|
|
20
23
|
* Tokenise rawText, encrypt it, store in vault, return the FPE token.
|
|
@@ -41,18 +44,11 @@ declare const adetokenizeText: typeof detokenizeText;
|
|
|
41
44
|
declare function looksLikeToken(value: string | any): boolean;
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* Generates structurally valid, **deterministic** tokens that preserve the
|
|
47
|
-
* format of the original data type so downstream tools, schemas, and
|
|
48
|
-
* validators continue to work without modification.
|
|
47
|
+
* Deterministic Pseudonymization (DP) token generation using NIST SP 800-38G FF1.
|
|
49
48
|
*/
|
|
50
|
-
/** Clear the cached master key. Useful in tests. */
|
|
51
49
|
declare function resetMasterKey(): void;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
*/
|
|
55
|
-
declare function generateFPEToken(rawText: string, entityType?: string): Promise<string>;
|
|
50
|
+
declare function generateDPToken(rawText: string, entityType?: string): Promise<string>;
|
|
51
|
+
declare const generateFPEToken: typeof generateDPToken;
|
|
56
52
|
|
|
57
53
|
/**
|
|
58
54
|
* Span Resolution Engine — Sweep-Line Overlap Resolver (TypeScript).
|
|
@@ -184,44 +180,43 @@ declare class MaskSecurityError extends MaskError {
|
|
|
184
180
|
/**
|
|
185
181
|
* Core cryptography engine for Mask SDK.
|
|
186
182
|
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
183
|
+
* Supports a JSON-based Keyring for transparent key rotation:
|
|
184
|
+
* MASK_KEYRING='{"v1":"oldkey...","v2":"newkey..."}'
|
|
185
|
+
* The *last* key in the JSON object is the active encryption key.
|
|
186
|
+
* All keys in the keyring are available for decryption (zero-downtime rotation).
|
|
190
187
|
*
|
|
191
|
-
*
|
|
192
|
-
* Includes a compatibility layer to decrypt legacy Fernet-format tokens.
|
|
188
|
+
* Legacy single-key mode (MASK_ENCRYPTION_KEY) is fully mapped to key ID "default".
|
|
193
189
|
*
|
|
194
|
-
*
|
|
190
|
+
* Ciphertext envelope format: aes:v2:{keyId}:{base64(iv+authTag+ciphertext)}
|
|
191
|
+
*
|
|
192
|
+
* Uses AES-256-GCM via native Node.js crypto and Argon2id for key derivation.
|
|
195
193
|
*/
|
|
196
194
|
declare class CryptoEngine {
|
|
197
195
|
private static _instance;
|
|
198
|
-
private
|
|
196
|
+
private _keyring;
|
|
197
|
+
private _activeKeyId;
|
|
199
198
|
private _indexSecret;
|
|
200
199
|
private constructor();
|
|
201
200
|
/**
|
|
202
201
|
* Return the singleton instance, initialising it if necessary.
|
|
203
|
-
*
|
|
202
|
+
* Async because Argon2id key derivation is async.
|
|
204
203
|
*/
|
|
205
204
|
static getInstanceAsync(): Promise<CryptoEngine>;
|
|
206
205
|
/** Legacy synchronous accessor — will throw if not already initialised. */
|
|
207
206
|
static getInstance(): CryptoEngine;
|
|
208
|
-
/** Clear the singleton
|
|
207
|
+
/** Clear the singleton (useful for key rotation / tests). */
|
|
209
208
|
static reset(): void;
|
|
209
|
+
private _deriveAesKey;
|
|
210
210
|
private _init;
|
|
211
211
|
/** Return the secret used for HMAC-based blind indexing. */
|
|
212
212
|
getIndexSecret(): Promise<Buffer>;
|
|
213
|
+
/** Encrypt plaintext using the active keyring key.
|
|
214
|
+
* Envelope format: aes:v2:{keyId}:{base64(iv+authTag+ciphertext)}
|
|
215
|
+
*/
|
|
213
216
|
encrypt(plaintext: string): string;
|
|
217
|
+
/** Decrypt ciphertext. Supports all historical envelope formats. */
|
|
214
218
|
decrypt(ciphertext: string): string;
|
|
215
|
-
/** Decrypt an AES-256-GCM token (base64 encoded). */
|
|
216
219
|
private _decryptAesGcm;
|
|
217
|
-
/**
|
|
218
|
-
* Attempt to decrypt a legacy Fernet-format token.
|
|
219
|
-
*
|
|
220
|
-
* Fernet format: Version (1) || Timestamp (8) || IV (16) || Ciphertext (var) || HMAC (32)
|
|
221
|
-
* All base64url-encoded.
|
|
222
|
-
*
|
|
223
|
-
* We try to use the `fernet` npm package if available, otherwise throw.
|
|
224
|
-
*/
|
|
225
220
|
private _decryptLegacyFernet;
|
|
226
221
|
}
|
|
227
222
|
|
|
@@ -236,13 +231,24 @@ declare class AuditLogger {
|
|
|
236
231
|
private _strictMode;
|
|
237
232
|
private _bufferFullWarned;
|
|
238
233
|
private _shutdownRegistered;
|
|
234
|
+
private _signingKey;
|
|
235
|
+
private _prevSig;
|
|
236
|
+
private _instanceId;
|
|
239
237
|
private constructor();
|
|
240
238
|
static getInstance(): AuditLogger;
|
|
239
|
+
private _getOverflowPath;
|
|
240
|
+
private _writeOverflow;
|
|
241
|
+
private _consumeOverflow;
|
|
241
242
|
log(action: string, token: string, dataType?: string, agent?: string, tool?: string, extra?: Record<string, any>): void;
|
|
242
243
|
start(): void;
|
|
243
244
|
stop(): Promise<void>;
|
|
244
245
|
private _flush;
|
|
245
|
-
/** Synchronous flush for use in signal handlers where async is unreliable.
|
|
246
|
+
/** Synchronous flush for use in signal handlers where async is unreliable.
|
|
247
|
+
*
|
|
248
|
+
* Computes HMAC signatures to maintain chain integrity and writes to the
|
|
249
|
+
* secure ndjson audit file (MASK_SECURE_AUDIT_LOG_DIR) if configured,
|
|
250
|
+
* ensuring SOC 2 tamper-evidence guarantees hold through process shutdown.
|
|
251
|
+
*/
|
|
246
252
|
private _flushSync;
|
|
247
253
|
}
|
|
248
254
|
|