spd-lib 1.3.0 → 1.3.2

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/index.d.ts ADDED
@@ -0,0 +1,263 @@
1
+ import sodium from 'libsodium-wrappers';
2
+
3
+ type HashAlgorithm = 'sha3-512' | 'sha256' | 'sha512';
4
+ type SupportedDataType = 'string' | 'number' | 'boolean' | 'object' | 'Array' | 'Uint8Array' | 'Uint16Array' | 'Uint32Array' | 'BigInt64Array' | 'BigUint64Array' | 'Float32Array' | 'Float64Array' | 'Map' | 'Set' | 'Date' | 'RegExp' | 'Error';
5
+ interface EncryptedDataEntry {
6
+ dataName: string;
7
+ nonce: Buffer;
8
+ data: Buffer;
9
+ hash: string;
10
+ dataType: SupportedDataType;
11
+ }
12
+ interface SerializedDataEntry {
13
+ dataName: string;
14
+ nonce: number[];
15
+ data: number[];
16
+ hash: string;
17
+ dataType: SupportedDataType;
18
+ }
19
+ interface SPDPayload {
20
+ data: SerializedDataEntry[];
21
+ encryptedSalt: number[];
22
+ saltNonce: number[];
23
+ wrapSalt: number[];
24
+ version: number;
25
+ hashAlgorithm?: string;
26
+ argon2Memory?: number;
27
+ argon2Time?: number;
28
+ }
29
+ interface SPDLegacyPayload {
30
+ data: SerializedDataEntry[];
31
+ salt: number[];
32
+ }
33
+ interface WrappedPayload {
34
+ payload: Buffer;
35
+ mac: Buffer;
36
+ }
37
+ interface SerializedWrappedPayload {
38
+ payload: number[];
39
+ mac: number[];
40
+ }
41
+ interface PQCKey {
42
+ privateKey: Uint8Array;
43
+ publicKey?: Uint8Array;
44
+ }
45
+ interface PQCKeyResult {
46
+ pqcKey: PQCKey;
47
+ salt: Uint8Array;
48
+ }
49
+ interface PBKResult {
50
+ pbk: Buffer;
51
+ salt: Uint8Array;
52
+ }
53
+ interface EncryptedSaltResult {
54
+ encryptedSalt: number[];
55
+ saltNonce: number[];
56
+ wrapSalt: number[];
57
+ }
58
+ interface DataInput {
59
+ name: string;
60
+ data: unknown;
61
+ }
62
+ interface SPDChunkManifest {
63
+ totalChunks: number;
64
+ chunkSize: number;
65
+ totalBytes: number;
66
+ version: number;
67
+ }
68
+ type TypedArray = Uint8Array | Uint16Array | Uint32Array | BigInt64Array | BigUint64Array | Float32Array | Float64Array;
69
+ type SupportedValue = string | number | boolean | unknown[] | TypedArray | Map<unknown, unknown> | Set<unknown> | Date | RegExp | Error | Record<string, unknown>;
70
+
71
+ declare class SPD {
72
+ private data;
73
+ private keyPair?;
74
+ private userKey?;
75
+ private macKey?;
76
+ private salt?;
77
+ private hash;
78
+ private compressionLevel;
79
+ private assertReady;
80
+ init(): Promise<void>;
81
+ changePasscode(oldPasscode: string, newPasscode: string): Promise<void>;
82
+ /**
83
+ * Derives a 512-bit master secret via Argon2id and splits it into:
84
+ * aeadKey (32 B) — XChaCha20-Poly1305 encryption key (256-bit, 128-bit PQ)
85
+ * macKey (32 B) — HMAC-SHA3-512 authentication key (domain-separated)
86
+ */
87
+ static deriveKeys(passcode: string, salt: Uint8Array, memory?: number, time?: number): Promise<{
88
+ aeadKey: Uint8Array;
89
+ macKey: Uint8Array;
90
+ }>;
91
+ private static computeMAC;
92
+ checkPasscodeStrength(passcode: string): boolean;
93
+ setPassKey(passcode: string): Promise<void>;
94
+ setHash(hash?: HashAlgorithm): void;
95
+ setCompressionLevel(level?: number): void;
96
+ getSodium(): typeof sodium;
97
+ sanitizeName(dataName: string): string;
98
+ addData(dataName: string, value: unknown): Promise<void>;
99
+ addMany(items: DataInput[]): Promise<void>;
100
+ extractData(): Promise<Record<string, unknown>>;
101
+ /**
102
+ * Memory-efficient streaming extraction.
103
+ *
104
+ * For each encrypted entry, this method:
105
+ * 1. Decrypts and decompresses the entry into a temp file in `tmpDir`
106
+ * (named `<entryName>.ssf`, mode 0600)
107
+ * 2. Reads the .ssf file and calls your `callback` with the name + value
108
+ * 3. Immediately deletes the .ssf file before moving to the next entry
109
+ *
110
+ * At most one entry's decrypted bytes exist on disk or in RAM at a time,
111
+ * so this works for arbitrarily large SPD files as long as a single entry
112
+ * fits in memory (which is always the case — entries are discrete values).
113
+ *
114
+ * @param tmpDir Directory to write temp files into (must exist, mode 0700 recommended)
115
+ * @param callback Called once per entry in order. Await is respected — the next
116
+ * entry won't be processed until your callback resolves.
117
+ *
118
+ * @example
119
+ * await spd.extractDataStreaming('/tmp/spd_scratch', async (name, value) => {
120
+ * console.log(name, value);
121
+ * });
122
+ */
123
+ extractDataStreaming(tmpDir: string, callback: (name: string, value: unknown) => Promise<void> | void): Promise<void>;
124
+ destroy(): void;
125
+ clearCache(): void;
126
+ saveToFile(outputPath: string, passcode: string): Promise<void>;
127
+ /**
128
+ * Saves to file using streaming I/O — supports files larger than 2 GB.
129
+ * Format: [8B LE uint64 plaintext length][64B HMAC-SHA3-512][zlib(plaintext)]
130
+ */
131
+ saveToFileStreaming(outputPath: string, passcode: string): Promise<void>;
132
+ saveData(passcode?: string): Promise<string>;
133
+ /**
134
+ * Splits the payload into base64 chunks for chunked internet transfer.
135
+ * The manifest (last element) records totalChunks/totalBytes for validation.
136
+ * Reassemble with `SPD.loadFromChunks(chunks, passcode)`.
137
+ */
138
+ saveDataChunked(passcode: string, chunkSize?: number): Promise<string[]>;
139
+ static loadFromFile(filePath: string, passcode: string): Promise<SPD>;
140
+ static loadFromFileStreaming(filePath: string, passcode: string): Promise<SPD>;
141
+ /**
142
+ * True constant-memory streaming extract from a binary SPD file.
143
+ *
144
+ * Unlike `loadFromFileStreaming` (which buffers the entire plaintext into RAM),
145
+ * this method pipes the inflate stream through a byte-by-byte parser that:
146
+ * 1. Reads and verifies the file header + MAC
147
+ * 2. Parses the metadata block to derive keys
148
+ * 3. Processes one entry at a time:
149
+ * a. Writes the encrypted entry to `<name>_enc.ssf` in `tmpDir` (mode 0600)
150
+ * b. Decrypts it, writes the plaintext to `<name>_dec.ssf`
151
+ * c. Reads the `.ssf` file and calls your `callback`
152
+ * d. Deletes both `.ssf` files before touching the next entry
153
+ *
154
+ * Peak RAM usage is proportional to the largest single entry, not the file size.
155
+ * Files of any size are supported as long as individual entries fit in memory.
156
+ *
157
+ * @param filePath Path to the `.spd` file written by `saveToFileStreaming`
158
+ * @param passcode Passcode used when the file was saved
159
+ * @param tmpDir Scratch directory for temp files (must exist, mode 0700 recommended)
160
+ * @param callback Called once per entry in order. Next entry waits for this to resolve.
161
+ *
162
+ * @example
163
+ * await SPD.extractFromFileStreaming('./huge.spd', 'MyPass!', '/tmp/spd', async (name, value) => {
164
+ * console.log(name, typeof value);
165
+ * });
166
+ */
167
+ static extractFromFileStreaming(filePath: string, passcode: string, tmpDir: string, callback: (name: string, value: unknown) => Promise<void> | void): Promise<void>;
168
+ static loadFromString(data: string, passcode: string): Promise<SPD>;
169
+ static loadFromChunks(chunks: string[], passcode: string): Promise<SPD>;
170
+ static derivePBK(passcode: string, salt: Uint8Array, memory?: number, time?: number): Promise<PBKResult>;
171
+ static decryptSalt(encryptedSalt: number[], saltNonce: number[], wrapSalt: number[], passcode: string, memory?: number, time?: number): Promise<Uint8Array>;
172
+ static encryptSalt(salt: Uint8Array, passcode: string): Promise<EncryptedSaltResult>;
173
+ static toBase64(data: Uint8Array | Buffer): string;
174
+ static fromBase64(data: string): Uint8Array;
175
+ private buildSerializedPayload;
176
+ private static parseSerializedPayload;
177
+ private buildBinaryPayload;
178
+ private static parseBinaryPayload;
179
+ private detectType;
180
+ private isTypedArray;
181
+ private isCollectionType;
182
+ private convertInputToString;
183
+ private convertStringToInput;
184
+ }
185
+
186
+ /**
187
+ * Legacy SPD class for backwards compatibility.
188
+ * Uses older cryptographic methods (crypto_secretbox instead of AEAD).
189
+ */
190
+ declare class SPDLegacy {
191
+ private data;
192
+ private keyPair?;
193
+ private userKey?;
194
+ private salt?;
195
+ constructor();
196
+ init(): Promise<void>;
197
+ setPassKey(passcode: string): Promise<void>;
198
+ addData(dataName: string, value: unknown): Promise<void>;
199
+ saveToFile(outputPath: string): void;
200
+ static loadFromFile(filePath: string, passcode: string): Promise<SPDLegacy>;
201
+ extractData(): Promise<Record<string, unknown>>;
202
+ static derivePBK(passcode: string, salt: Uint8Array): Promise<PBKResult>;
203
+ saveData(): Buffer;
204
+ static loadFromString(data: string, passcode: string): Promise<SPDLegacy>;
205
+ private convertPasscodeToPQCKeySalted;
206
+ convertPasscodeToPQCKey(passcode: string): Promise<PQCKeyResult>;
207
+ private detectType;
208
+ private isTypedArray;
209
+ private isCollectionType;
210
+ private isSpecialType;
211
+ private convertInputToString;
212
+ private convertStringToInput;
213
+ }
214
+
215
+ /**
216
+ * In-memory key vault with automatic expiration.
217
+ * Keys are automatically deleted after the specified timeout.
218
+ */
219
+ declare class SPDVault {
220
+ private keys;
221
+ private timers;
222
+ private timeoutMs;
223
+ constructor(timeoutMs?: number);
224
+ /**
225
+ * Generate a random key string.
226
+ */
227
+ private generateRandomKey;
228
+ /**
229
+ * Reset the expiration timer for a key.
230
+ */
231
+ private resetTimer;
232
+ /**
233
+ * Generate and store a new random key.
234
+ */
235
+ genKey(keyId?: string): void;
236
+ /**
237
+ * Store a custom key.
238
+ */
239
+ pushKey(keyId?: string, key?: string): void;
240
+ /**
241
+ * Retrieve a key by ID.
242
+ * Returns undefined if the key doesn't exist.
243
+ */
244
+ pullKey(keyId?: string): string | undefined;
245
+ /**
246
+ * Delete a key by ID.
247
+ */
248
+ destroyKey(keyId?: string): void;
249
+ /**
250
+ * Update a key if the old value matches.
251
+ */
252
+ updateKey(keyId: string, oldValue?: string, newValue?: string): void;
253
+ /**
254
+ * Stop all expiration timers.
255
+ */
256
+ stop(): void;
257
+ /**
258
+ * Clear all keys and timers.
259
+ */
260
+ destroy(): void;
261
+ }
262
+
263
+ export { type DataInput, type EncryptedDataEntry, type EncryptedSaltResult, type HashAlgorithm, type PBKResult, type PQCKey, type PQCKeyResult, SPD, type SPDChunkManifest, SPDLegacy, type SPDLegacyPayload, type SPDPayload, SPDVault, SPDLegacy as SPD_LEG, SPDVault as SPD_Vault, type SerializedDataEntry, type SerializedWrappedPayload, type SupportedDataType, type SupportedValue, type TypedArray, type WrappedPayload };