@happyvertical/encryption 0.74.8

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.
@@ -0,0 +1,79 @@
1
+ import { BaseEncryption } from '../shared/base.js';
2
+ import { DecryptOptions, EncryptionCapabilities, EncryptOptions, ExportKeyOptions, ImportKeyOptions, Key, KeyPair, KeyPairOptions, PGPOptions, SignOptions, VerifyOptions } from '../shared/types.js';
3
+ /**
4
+ * PGP/OpenPGP encryption adapter
5
+ *
6
+ * Uses OpenPGP.js for encryption, decryption, signing, and key management.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const pgp = new PGPEncryption({
11
+ * type: 'pgp',
12
+ * publicKey: recipientPublicKey,
13
+ * privateKey: myPrivateKey,
14
+ * passphrase: 'my-passphrase'
15
+ * });
16
+ *
17
+ * const encrypted = await pgp.encryptText('Secret message');
18
+ * const decrypted = await pgp.decryptText(encrypted);
19
+ * ```
20
+ */
21
+ export declare class PGPEncryption extends BaseEncryption {
22
+ private options;
23
+ private publicKeys?;
24
+ private privateKeys?;
25
+ constructor(options: PGPOptions);
26
+ /**
27
+ * Initialize keys from options
28
+ */
29
+ private initializeKeys;
30
+ /**
31
+ * Get public keys for encryption
32
+ */
33
+ private getPublicKeys;
34
+ /**
35
+ * Get private keys for decryption
36
+ */
37
+ private getPrivateKeys;
38
+ encryptText(text: string, options?: EncryptOptions): Promise<string>;
39
+ decryptText(encrypted: string, options?: DecryptOptions): Promise<string>;
40
+ encryptBuffer(buffer: Buffer, options?: EncryptOptions): Promise<Buffer>;
41
+ decryptBuffer(buffer: Buffer, options?: DecryptOptions): Promise<Buffer>;
42
+ generateKeyPair(options?: KeyPairOptions): Promise<KeyPair>;
43
+ importKey(key: string | Buffer, options?: ImportKeyOptions): Promise<Key>;
44
+ exportKey(key: Key, options?: ExportKeyOptions): Promise<string | Buffer>;
45
+ /**
46
+ * Sign data with private key
47
+ */
48
+ sign(data: string | Buffer, options?: SignOptions): Promise<string | Buffer>;
49
+ /**
50
+ * Verify signature
51
+ */
52
+ verify(data: string | Buffer, signature: string | Buffer, options?: VerifyOptions): Promise<boolean>;
53
+ /**
54
+ * Encrypt email message in PGP/MIME format
55
+ */
56
+ encryptEmail(message: import('../shared/types.js').EmailMessage, options?: import('../shared/types.js').EncryptEmailOptions): Promise<import('../shared/types.js').EmailMessage>;
57
+ /**
58
+ * Decrypt PGP/MIME email message
59
+ */
60
+ decryptEmail(message: import('../shared/types.js').EmailMessage, options?: import('../shared/types.js').DecryptEmailOptions): Promise<import('../shared/types.js').DecryptedEmail>;
61
+ /**
62
+ * Sign email message
63
+ */
64
+ signEmail(message: import('../shared/types.js').EmailMessage, options?: import('../shared/types.js').SignEmailOptions): Promise<import('../shared/types.js').EmailMessage>;
65
+ /**
66
+ * Verify email signature
67
+ */
68
+ verifyEmail(message: import('../shared/types.js').EmailMessage, options?: import('../shared/types.js').VerifyEmailOptions): Promise<import('../shared/types.js').VerificationResult>;
69
+ /**
70
+ * Serialize email content for encryption/signing
71
+ */
72
+ private serializeEmailContent;
73
+ /**
74
+ * Deserialize email content after decryption
75
+ */
76
+ private deserializeEmailContent;
77
+ getCapabilities(): Promise<EncryptionCapabilities>;
78
+ }
79
+ //# sourceMappingURL=pgp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pgp.d.ts","sourceRoot":"","sources":["../../src/adapters/pgp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAUnD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,GAAG,EACH,OAAO,EACP,cAAc,EACd,UAAU,EACV,WAAW,EACX,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAc,SAAQ,cAAc;IAC/C,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,UAAU,CAAC,CAAsB;IACzC,OAAO,CAAC,WAAW,CAAC,CAAuB;gBAE/B,OAAO,EAAE,UAAU;IAK/B;;OAEG;YACW,cAAc;IA2D5B;;OAEG;YACW,aAAa;IAsB3B;;OAEG;YACW,cAAc;IAgCtB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAqDpE,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA6EZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IA0DZ,aAAa,CACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC;IAqEZ,eAAe,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAqE3D,SAAS,CACb,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,GAAG,CAAC;IAqFT,SAAS,CACb,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAgC3B;;OAEG;IACG,IAAI,CACR,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAgE3B;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,SAAS,EAAE,MAAM,GAAG,MAAM,EAC1B,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,OAAO,CAAC;IAkFnB;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,OAAO,oBAAoB,EAAE,YAAY,EAClD,OAAO,CAAC,EAAE,OAAO,oBAAoB,EAAE,mBAAmB,GACzD,OAAO,CAAC,OAAO,oBAAoB,EAAE,YAAY,CAAC;IAuErD;;OAEG;IACG,YAAY,CAChB,OAAO,EAAE,OAAO,oBAAoB,EAAE,YAAY,EAClD,OAAO,CAAC,EAAE,OAAO,oBAAoB,EAAE,mBAAmB,GACzD,OAAO,CAAC,OAAO,oBAAoB,EAAE,cAAc,CAAC;IAkHvD;;OAEG;IACG,SAAS,CACb,OAAO,EAAE,OAAO,oBAAoB,EAAE,YAAY,EAClD,OAAO,CAAC,EAAE,OAAO,oBAAoB,EAAE,gBAAgB,GACtD,OAAO,CAAC,OAAO,oBAAoB,EAAE,YAAY,CAAC;IA8DrD;;OAEG;IACG,WAAW,CACf,OAAO,EAAE,OAAO,oBAAoB,EAAE,YAAY,EAClD,OAAO,CAAC,EAAE,OAAO,oBAAoB,EAAE,kBAAkB,GACxD,OAAO,CAAC,OAAO,oBAAoB,EAAE,kBAAkB,CAAC;IAwD3D;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAkC7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAkCzB,eAAe,IAAI,OAAO,CAAC,sBAAsB,CAAC;CAgBzD"}
@@ -0,0 +1,454 @@
1
+ import nacl from "tweetnacl";
2
+ import { decodeBase64, decodeUTF8, encodeBase64, encodeUTF8 } from "tweetnacl-util";
3
+ import { BaseEncryption, InvalidKeyError, EncryptError, DecryptError, KeyError, SignatureError } from "../index.js";
4
+ class NaClEncryption extends BaseEncryption {
5
+ options;
6
+ secretKey;
7
+ publicKey;
8
+ constructor(options) {
9
+ super("nacl", options.debug);
10
+ this.options = options;
11
+ this.initializeKeys();
12
+ }
13
+ /**
14
+ * Initialize keys from options
15
+ */
16
+ initializeKeys() {
17
+ const encoding = this.options.encoding || "base64";
18
+ if (this.options.secretKey) {
19
+ this.secretKey = this.parseKey(this.options.secretKey, encoding);
20
+ if (this.secretKey.length !== nacl.secretbox.keyLength) {
21
+ throw new InvalidKeyError(
22
+ `NaCl secret key must be ${nacl.secretbox.keyLength} bytes`,
23
+ this.adapterType
24
+ );
25
+ }
26
+ }
27
+ if (this.options.publicKey) {
28
+ this.publicKey = this.parseKey(this.options.publicKey, encoding);
29
+ if (this.publicKey.length !== nacl.box.publicKeyLength) {
30
+ throw new InvalidKeyError(
31
+ `NaCl public key must be ${nacl.box.publicKeyLength} bytes`,
32
+ this.adapterType
33
+ );
34
+ }
35
+ }
36
+ }
37
+ /**
38
+ * Parse key from various formats
39
+ */
40
+ parseKey(key, encoding) {
41
+ if (key instanceof Uint8Array) {
42
+ return key;
43
+ }
44
+ if (Buffer.isBuffer(key)) {
45
+ return new Uint8Array(key);
46
+ }
47
+ if (typeof key === "string") {
48
+ if (encoding === "base64") {
49
+ return decodeBase64(key);
50
+ }
51
+ if (encoding === "hex") {
52
+ return new Uint8Array(Buffer.from(key, "hex"));
53
+ }
54
+ if (encoding === "utf8") {
55
+ return decodeUTF8(key);
56
+ }
57
+ }
58
+ throw new InvalidKeyError("Invalid key format for NaCl", this.adapterType);
59
+ }
60
+ /**
61
+ * Format key for output
62
+ */
63
+ formatKey(key, encoding = "base64") {
64
+ if (encoding === "base64") {
65
+ return encodeBase64(key);
66
+ }
67
+ if (encoding === "hex") {
68
+ return Buffer.from(key).toString("hex");
69
+ }
70
+ if (encoding === "utf8") {
71
+ return encodeUTF8(key);
72
+ }
73
+ return encodeBase64(key);
74
+ }
75
+ async encryptText(text, options) {
76
+ try {
77
+ this.log("Encrypting text", { length: text.length });
78
+ const message = decodeUTF8(text);
79
+ if (options?.recipientPublicKey) {
80
+ return this.encryptAsymmetric(message, options);
81
+ }
82
+ return this.encryptSymmetric(message);
83
+ } catch (error) {
84
+ throw new EncryptError(
85
+ `Failed to encrypt text: ${error.message}`,
86
+ this.adapterType,
87
+ error
88
+ );
89
+ }
90
+ }
91
+ async decryptText(encrypted, options) {
92
+ try {
93
+ this.log("Decrypting text", { length: encrypted.length });
94
+ const encryptedData = decodeBase64(encrypted);
95
+ const nonceLength = nacl.secretbox.nonceLength;
96
+ const nonce = encryptedData.slice(0, nonceLength);
97
+ const ciphertext = encryptedData.slice(nonceLength);
98
+ let decrypted;
99
+ if (this.publicKey && this.secretKey) {
100
+ if (ciphertext.length > nacl.box.publicKeyLength) {
101
+ const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);
102
+ const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);
103
+ decrypted = nacl.box.open(
104
+ actualCiphertext,
105
+ nonce,
106
+ senderPublicKey,
107
+ this.secretKey
108
+ );
109
+ if (decrypted) {
110
+ this.log("Text decrypted successfully (asymmetric)");
111
+ return encodeUTF8(decrypted);
112
+ }
113
+ }
114
+ }
115
+ if (this.secretKey) {
116
+ decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);
117
+ if (decrypted) {
118
+ this.log("Text decrypted successfully (symmetric)");
119
+ return encodeUTF8(decrypted);
120
+ }
121
+ }
122
+ throw new DecryptError(
123
+ "Decryption failed: invalid key or corrupted ciphertext",
124
+ this.adapterType
125
+ );
126
+ } catch (error) {
127
+ if (error instanceof DecryptError) {
128
+ throw error;
129
+ }
130
+ throw new DecryptError(
131
+ `Failed to decrypt text: ${error.message}`,
132
+ this.adapterType,
133
+ error
134
+ );
135
+ }
136
+ }
137
+ async encryptBuffer(buffer, options) {
138
+ try {
139
+ this.log("Encrypting buffer", { size: buffer.length });
140
+ const message = new Uint8Array(buffer);
141
+ if (options?.recipientPublicKey) {
142
+ const encrypted2 = this.encryptAsymmetric(message, options);
143
+ return Buffer.from(decodeBase64(encrypted2));
144
+ }
145
+ const encrypted = this.encryptSymmetric(message);
146
+ return Buffer.from(decodeBase64(encrypted));
147
+ } catch (error) {
148
+ throw new EncryptError(
149
+ `Failed to encrypt buffer: ${error.message}`,
150
+ this.adapterType,
151
+ error
152
+ );
153
+ }
154
+ }
155
+ async decryptBuffer(buffer, options) {
156
+ try {
157
+ this.log("Decrypting buffer", { size: buffer.length });
158
+ const decoded = decodeBase64(buffer.toString("base64"));
159
+ const nonce = decoded.slice(0, nacl.secretbox.nonceLength);
160
+ const ciphertext = decoded.slice(nacl.secretbox.nonceLength);
161
+ let decrypted = null;
162
+ if (this.publicKey && this.secretKey) {
163
+ if (ciphertext.length > nacl.box.publicKeyLength) {
164
+ const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);
165
+ const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);
166
+ decrypted = nacl.box.open(
167
+ actualCiphertext,
168
+ nonce,
169
+ senderPublicKey,
170
+ this.secretKey
171
+ );
172
+ if (decrypted) {
173
+ this.log("Buffer decrypted successfully (asymmetric)");
174
+ return Buffer.from(decrypted);
175
+ }
176
+ }
177
+ }
178
+ if (this.secretKey) {
179
+ decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);
180
+ if (decrypted) {
181
+ this.log("Buffer decrypted successfully (symmetric)");
182
+ return Buffer.from(decrypted);
183
+ }
184
+ }
185
+ throw new DecryptError(
186
+ "Decryption failed: invalid key or corrupted ciphertext",
187
+ this.adapterType
188
+ );
189
+ } catch (error) {
190
+ if (error instanceof DecryptError) {
191
+ throw error;
192
+ }
193
+ throw new DecryptError(
194
+ `Failed to decrypt buffer: ${error.message}`,
195
+ this.adapterType,
196
+ error
197
+ );
198
+ }
199
+ }
200
+ /**
201
+ * Symmetric encryption using secretbox
202
+ */
203
+ encryptSymmetric(message) {
204
+ if (!this.secretKey) {
205
+ throw new KeyError(
206
+ "Secret key required for symmetric encryption",
207
+ this.adapterType
208
+ );
209
+ }
210
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
211
+ const ciphertext = nacl.secretbox(message, nonce, this.secretKey);
212
+ const encrypted = new Uint8Array(nonce.length + ciphertext.length);
213
+ encrypted.set(nonce);
214
+ encrypted.set(ciphertext, nonce.length);
215
+ return encodeBase64(encrypted);
216
+ }
217
+ /**
218
+ * Asymmetric encryption using box
219
+ */
220
+ encryptAsymmetric(message, options) {
221
+ if (!this.secretKey) {
222
+ throw new KeyError(
223
+ "Secret key required for asymmetric encryption",
224
+ this.adapterType
225
+ );
226
+ }
227
+ const recipientPublicKey = this.parseKey(
228
+ options.recipientPublicKey,
229
+ this.options.encoding || "base64"
230
+ );
231
+ if (recipientPublicKey.length !== nacl.box.publicKeyLength) {
232
+ throw new InvalidKeyError(
233
+ `Recipient public key must be ${nacl.box.publicKeyLength} bytes`,
234
+ this.adapterType
235
+ );
236
+ }
237
+ const nonce = nacl.randomBytes(nacl.box.nonceLength);
238
+ const ciphertext = nacl.box(
239
+ message,
240
+ nonce,
241
+ recipientPublicKey,
242
+ this.secretKey
243
+ );
244
+ const senderPublicKey = this.publicKey || nacl.box.keyPair.fromSecretKey(this.secretKey).publicKey;
245
+ const encrypted = new Uint8Array(
246
+ nonce.length + senderPublicKey.length + ciphertext.length
247
+ );
248
+ encrypted.set(nonce);
249
+ encrypted.set(senderPublicKey, nonce.length);
250
+ encrypted.set(ciphertext, nonce.length + senderPublicKey.length);
251
+ return encodeBase64(encrypted);
252
+ }
253
+ async generateKeyPair(options) {
254
+ try {
255
+ this.log("Generating NaCl key pair", options);
256
+ const keyType = options?.type || "box";
257
+ if (keyType === "box" || keyType === "ecdh") {
258
+ const keypair = nacl.box.keyPair();
259
+ this.log("Encryption key pair generated");
260
+ return {
261
+ publicKey: keypair.publicKey,
262
+ privateKey: keypair.secretKey
263
+ };
264
+ }
265
+ if (keyType === "ecdsa") {
266
+ const keypair = nacl.sign.keyPair();
267
+ this.log("Signing key pair generated");
268
+ return {
269
+ publicKey: keypair.publicKey,
270
+ privateKey: keypair.secretKey
271
+ };
272
+ }
273
+ throw new KeyError(
274
+ `Unsupported key type for NaCl: ${keyType}. Use 'box' for encryption or 'sign' for signatures.`,
275
+ this.adapterType
276
+ );
277
+ } catch (error) {
278
+ throw new KeyError(
279
+ `Failed to generate NaCl key pair: ${error.message}`,
280
+ this.adapterType,
281
+ error
282
+ );
283
+ }
284
+ }
285
+ async importKey(key, options) {
286
+ try {
287
+ this.log("Importing NaCl key");
288
+ const encoding = this.options.encoding || "base64";
289
+ const keyData = typeof key === "string" ? key : key.toString(encoding);
290
+ const keyBytes = this.parseKey(keyData, encoding);
291
+ const keyType = options?.type || "public";
292
+ const format = options?.format || "armored";
293
+ const expectedLength = keyType === "public" ? nacl.box.publicKeyLength : nacl.box.secretKeyLength;
294
+ if (keyBytes.length !== expectedLength) {
295
+ throw new InvalidKeyError(
296
+ `NaCl ${keyType} key must be ${expectedLength} bytes`,
297
+ this.adapterType
298
+ );
299
+ }
300
+ this.log("Key imported successfully");
301
+ return {
302
+ type: keyType,
303
+ format,
304
+ data: keyData,
305
+ algorithm: "nacl"
306
+ };
307
+ } catch (error) {
308
+ throw new InvalidKeyError(
309
+ `Failed to import NaCl key: ${error.message}`,
310
+ this.adapterType,
311
+ error
312
+ );
313
+ }
314
+ }
315
+ async exportKey(key, options) {
316
+ try {
317
+ this.log("Exporting NaCl key");
318
+ const format = options?.format || key.format || "armored";
319
+ const encoding = this.options.encoding || "base64";
320
+ if (typeof key.data === "string") {
321
+ if (format === "binary") {
322
+ return Buffer.from(key.data, encoding);
323
+ }
324
+ return key.data;
325
+ }
326
+ if (Buffer.isBuffer(key.data)) {
327
+ if (format === "armored") {
328
+ return key.data.toString(encoding);
329
+ }
330
+ return key.data;
331
+ }
332
+ if (key.data instanceof Uint8Array) {
333
+ if (format === "binary") {
334
+ return Buffer.from(key.data);
335
+ }
336
+ return this.formatKey(key.data, encoding);
337
+ }
338
+ throw new InvalidKeyError(
339
+ "Invalid key data format for export",
340
+ this.adapterType
341
+ );
342
+ } catch (error) {
343
+ throw new KeyError(
344
+ `Failed to export NaCl key: ${error.message}`,
345
+ this.adapterType,
346
+ error
347
+ );
348
+ }
349
+ }
350
+ /**
351
+ * Sign data with signing key
352
+ */
353
+ async sign(data, options) {
354
+ try {
355
+ this.log("Signing data");
356
+ let signingKey;
357
+ if (options?.privateKey) {
358
+ signingKey = this.parseKey(
359
+ options.privateKey,
360
+ this.options.encoding || "base64"
361
+ );
362
+ } else if (this.secretKey) {
363
+ signingKey = this.secretKey;
364
+ } else {
365
+ throw new KeyError("No signing key available", this.adapterType);
366
+ }
367
+ if (signingKey.length !== nacl.sign.secretKeyLength) {
368
+ throw new InvalidKeyError(
369
+ `NaCl signing key must be ${nacl.sign.secretKeyLength} bytes`,
370
+ this.adapterType
371
+ );
372
+ }
373
+ const message = typeof data === "string" ? decodeUTF8(data) : new Uint8Array(data);
374
+ const signed = nacl.sign(message, signingKey);
375
+ this.log("Data signed successfully");
376
+ if (typeof data === "string") {
377
+ return encodeBase64(signed);
378
+ }
379
+ return Buffer.from(signed);
380
+ } catch (error) {
381
+ throw new SignatureError(
382
+ `Failed to sign data: ${error.message}`,
383
+ this.adapterType,
384
+ error
385
+ );
386
+ }
387
+ }
388
+ /**
389
+ * Verify signature
390
+ */
391
+ async verify(data, signature, options) {
392
+ try {
393
+ this.log("Verifying signature");
394
+ if (!options?.publicKey) {
395
+ throw new KeyError(
396
+ "Public key required for signature verification",
397
+ this.adapterType
398
+ );
399
+ }
400
+ const verificationKey = this.parseKey(
401
+ options.publicKey,
402
+ this.options.encoding || "base64"
403
+ );
404
+ if (verificationKey.length !== nacl.sign.publicKeyLength) {
405
+ throw new InvalidKeyError(
406
+ `NaCl verification key must be ${nacl.sign.publicKeyLength} bytes`,
407
+ this.adapterType
408
+ );
409
+ }
410
+ const signedMessage = typeof signature === "string" ? decodeBase64(signature) : new Uint8Array(signature);
411
+ const verified = nacl.sign.open(signedMessage, verificationKey);
412
+ if (!verified) {
413
+ this.log("Signature verification failed");
414
+ return false;
415
+ }
416
+ const originalMessage = typeof data === "string" ? decodeUTF8(data) : new Uint8Array(data);
417
+ if (verified.length !== originalMessage.length) {
418
+ this.log("Signature verification failed: message mismatch");
419
+ return false;
420
+ }
421
+ for (let i = 0; i < verified.length; i++) {
422
+ if (verified[i] !== originalMessage[i]) {
423
+ this.log("Signature verification failed: message mismatch");
424
+ return false;
425
+ }
426
+ }
427
+ this.log("Signature verified successfully");
428
+ return true;
429
+ } catch (error) {
430
+ this.log("Signature verification failed", error);
431
+ return false;
432
+ }
433
+ }
434
+ async getCapabilities() {
435
+ return {
436
+ textEncryption: true,
437
+ fileEncryption: true,
438
+ bufferEncryption: true,
439
+ streamEncryption: false,
440
+ emailEncryption: false,
441
+ signing: true,
442
+ verification: true,
443
+ keyGeneration: true,
444
+ keyManagement: true,
445
+ multipleRecipients: false,
446
+ symmetricEncryption: true,
447
+ asymmetricEncryption: true
448
+ };
449
+ }
450
+ }
451
+ export {
452
+ NaClEncryption
453
+ };
454
+ //# sourceMappingURL=nacl-CoiIhzki.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nacl-CoiIhzki.js","sources":["../../src/adapters/nacl.ts"],"sourcesContent":["import nacl from 'tweetnacl';\nimport {\n decodeBase64,\n decodeUTF8,\n encodeBase64,\n encodeUTF8,\n} from 'tweetnacl-util';\nimport { BaseEncryption } from '../shared/base.js';\nimport {\n DecryptError,\n EncryptError,\n InvalidKeyError,\n KeyError,\n SignatureError,\n} from '../shared/errors.js';\nimport type {\n DecryptOptions,\n EncryptionCapabilities,\n EncryptOptions,\n ExportKeyOptions,\n ImportKeyOptions,\n Key,\n KeyPair,\n KeyPairOptions,\n NaClOptions,\n SignOptions,\n VerifyOptions,\n} from '../shared/types.js';\n\n/**\n * NaCl/TweetNaCl encryption adapter\n *\n * Provides fast, modern cryptography using the NaCl library.\n * Supports both symmetric (secretbox) and asymmetric (box) encryption.\n *\n * @example\n * ```typescript\n * // Symmetric encryption\n * const nacl = new NaClEncryption({\n * type: 'nacl',\n * secretKey: secretKey\n * });\n *\n * const encrypted = await nacl.encryptText('Secret message');\n * const decrypted = await nacl.decryptText(encrypted);\n *\n * // Asymmetric encryption\n * const nacl = new NaClEncryption({\n * type: 'nacl',\n * publicKey: theirPublicKey,\n * secretKey: mySecretKey\n * });\n *\n * const encrypted = await nacl.encryptText('Secret message', {\n * recipientPublicKey: theirPublicKey\n * });\n * const decrypted = await nacl.decryptText(encrypted);\n * ```\n */\nexport class NaClEncryption extends BaseEncryption {\n private options: NaClOptions;\n private secretKey?: Uint8Array;\n private publicKey?: Uint8Array;\n\n constructor(options: NaClOptions) {\n super('nacl', options.debug);\n this.options = options;\n this.initializeKeys();\n }\n\n /**\n * Initialize keys from options\n */\n private initializeKeys(): void {\n const encoding = this.options.encoding || 'base64';\n\n // Initialize secret key for symmetric encryption\n if (this.options.secretKey) {\n this.secretKey = this.parseKey(this.options.secretKey, encoding);\n if (this.secretKey.length !== nacl.secretbox.keyLength) {\n throw new InvalidKeyError(\n `NaCl secret key must be ${nacl.secretbox.keyLength} bytes`,\n this.adapterType,\n );\n }\n }\n\n // Initialize public key for asymmetric encryption\n if (this.options.publicKey) {\n this.publicKey = this.parseKey(this.options.publicKey, encoding);\n if (this.publicKey.length !== nacl.box.publicKeyLength) {\n throw new InvalidKeyError(\n `NaCl public key must be ${nacl.box.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n }\n }\n\n /**\n * Parse key from various formats\n */\n private parseKey(\n key: Uint8Array | Buffer | string,\n encoding: 'base64' | 'hex' | 'utf8',\n ): Uint8Array {\n if (key instanceof Uint8Array) {\n return key;\n }\n\n if (Buffer.isBuffer(key)) {\n return new Uint8Array(key);\n }\n\n if (typeof key === 'string') {\n if (encoding === 'base64') {\n return decodeBase64(key);\n }\n if (encoding === 'hex') {\n return new Uint8Array(Buffer.from(key, 'hex'));\n }\n if (encoding === 'utf8') {\n return decodeUTF8(key);\n }\n }\n\n throw new InvalidKeyError('Invalid key format for NaCl', this.adapterType);\n }\n\n /**\n * Format key for output\n */\n private formatKey(\n key: Uint8Array,\n encoding: 'base64' | 'hex' | 'utf8' = 'base64',\n ): string {\n if (encoding === 'base64') {\n return encodeBase64(key);\n }\n if (encoding === 'hex') {\n return Buffer.from(key).toString('hex');\n }\n if (encoding === 'utf8') {\n return encodeUTF8(key);\n }\n return encodeBase64(key);\n }\n\n async encryptText(text: string, options?: EncryptOptions): Promise<string> {\n try {\n this.log('Encrypting text', { length: text.length });\n\n const message = decodeUTF8(text);\n\n // Check if asymmetric or symmetric encryption\n if (options?.recipientPublicKey) {\n // Asymmetric encryption (box)\n return this.encryptAsymmetric(message, options);\n }\n\n // Symmetric encryption (secretbox)\n return this.encryptSymmetric(message);\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt text: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async decryptText(\n encrypted: string,\n options?: DecryptOptions,\n ): Promise<string> {\n try {\n this.log('Decrypting text', { length: encrypted.length });\n\n // Decode the encrypted message\n const encryptedData = decodeBase64(encrypted);\n\n // Extract nonce and ciphertext\n const nonceLength = nacl.secretbox.nonceLength;\n const nonce = encryptedData.slice(0, nonceLength);\n const ciphertext = encryptedData.slice(nonceLength);\n\n let decrypted: Uint8Array | null;\n\n // Try asymmetric decryption first if we have keys\n if (this.publicKey && this.secretKey) {\n // Check if there's a public key in the message (for box)\n if (ciphertext.length > nacl.box.publicKeyLength) {\n const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);\n const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);\n\n decrypted = nacl.box.open(\n actualCiphertext,\n nonce,\n senderPublicKey,\n this.secretKey,\n );\n\n if (decrypted) {\n this.log('Text decrypted successfully (asymmetric)');\n return encodeUTF8(decrypted);\n }\n }\n }\n\n // Try symmetric decryption\n if (this.secretKey) {\n decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);\n\n if (decrypted) {\n this.log('Text decrypted successfully (symmetric)');\n return encodeUTF8(decrypted);\n }\n }\n\n throw new DecryptError(\n 'Decryption failed: invalid key or corrupted ciphertext',\n this.adapterType,\n );\n } catch (error) {\n if (error instanceof DecryptError) {\n throw error;\n }\n throw new DecryptError(\n `Failed to decrypt text: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async encryptBuffer(\n buffer: Buffer,\n options?: EncryptOptions,\n ): Promise<Buffer> {\n try {\n this.log('Encrypting buffer', { size: buffer.length });\n\n const message = new Uint8Array(buffer);\n\n // Check if asymmetric or symmetric encryption\n if (options?.recipientPublicKey) {\n // Asymmetric encryption (box)\n const encrypted = this.encryptAsymmetric(message, options);\n return Buffer.from(decodeBase64(encrypted));\n }\n\n // Symmetric encryption (secretbox)\n const encrypted = this.encryptSymmetric(message);\n return Buffer.from(decodeBase64(encrypted));\n } catch (error) {\n throw new EncryptError(\n `Failed to encrypt buffer: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async decryptBuffer(\n buffer: Buffer,\n options?: DecryptOptions,\n ): Promise<Buffer> {\n try {\n this.log('Decrypting buffer', { size: buffer.length });\n\n // Decode the base64 buffer\n const decoded = decodeBase64(buffer.toString('base64'));\n\n // Extract nonce and ciphertext\n const nonce = decoded.slice(0, nacl.secretbox.nonceLength);\n const ciphertext = decoded.slice(nacl.secretbox.nonceLength);\n\n let decrypted: Uint8Array | null = null;\n\n // Try asymmetric decryption first if we have keys\n if (this.publicKey && this.secretKey) {\n // Check if there's a public key in the message (for box)\n if (ciphertext.length > nacl.box.publicKeyLength) {\n const senderPublicKey = ciphertext.slice(0, nacl.box.publicKeyLength);\n const actualCiphertext = ciphertext.slice(nacl.box.publicKeyLength);\n\n decrypted = nacl.box.open(\n actualCiphertext,\n nonce,\n senderPublicKey,\n this.secretKey,\n );\n\n if (decrypted) {\n this.log('Buffer decrypted successfully (asymmetric)');\n return Buffer.from(decrypted);\n }\n }\n }\n\n // Try symmetric decryption\n if (this.secretKey) {\n decrypted = nacl.secretbox.open(ciphertext, nonce, this.secretKey);\n\n if (decrypted) {\n this.log('Buffer decrypted successfully (symmetric)');\n return Buffer.from(decrypted);\n }\n }\n\n throw new DecryptError(\n 'Decryption failed: invalid key or corrupted ciphertext',\n this.adapterType,\n );\n } catch (error) {\n if (error instanceof DecryptError) {\n throw error;\n }\n throw new DecryptError(\n `Failed to decrypt buffer: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Symmetric encryption using secretbox\n */\n private encryptSymmetric(message: Uint8Array): string {\n if (!this.secretKey) {\n throw new KeyError(\n 'Secret key required for symmetric encryption',\n this.adapterType,\n );\n }\n\n // Generate random nonce\n const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);\n\n // Encrypt the message\n const ciphertext = nacl.secretbox(message, nonce, this.secretKey);\n\n // Combine nonce and ciphertext\n const encrypted = new Uint8Array(nonce.length + ciphertext.length);\n encrypted.set(nonce);\n encrypted.set(ciphertext, nonce.length);\n\n return encodeBase64(encrypted);\n }\n\n /**\n * Asymmetric encryption using box\n */\n private encryptAsymmetric(\n message: Uint8Array,\n options: EncryptOptions,\n ): string {\n if (!this.secretKey) {\n throw new KeyError(\n 'Secret key required for asymmetric encryption',\n this.adapterType,\n );\n }\n\n // Get recipient public key\n const recipientPublicKey = this.parseKey(\n options.recipientPublicKey as string | Uint8Array | Buffer,\n this.options.encoding || 'base64',\n );\n\n if (recipientPublicKey.length !== nacl.box.publicKeyLength) {\n throw new InvalidKeyError(\n `Recipient public key must be ${nacl.box.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Generate random nonce\n const nonce = nacl.randomBytes(nacl.box.nonceLength);\n\n // Encrypt the message\n const ciphertext = nacl.box(\n message,\n nonce,\n recipientPublicKey,\n this.secretKey,\n );\n\n // Include sender's public key in the message\n const senderPublicKey =\n this.publicKey ||\n nacl.box.keyPair.fromSecretKey(this.secretKey).publicKey;\n\n // Combine nonce, sender public key, and ciphertext\n const encrypted = new Uint8Array(\n nonce.length + senderPublicKey.length + ciphertext.length,\n );\n encrypted.set(nonce);\n encrypted.set(senderPublicKey, nonce.length);\n encrypted.set(ciphertext, nonce.length + senderPublicKey.length);\n\n return encodeBase64(encrypted);\n }\n\n async generateKeyPair(options?: KeyPairOptions): Promise<KeyPair> {\n try {\n this.log('Generating NaCl key pair', options);\n\n const keyType = options?.type || 'box';\n\n if (keyType === 'box' || keyType === 'ecdh') {\n // Generate encryption keypair\n const keypair = nacl.box.keyPair();\n\n this.log('Encryption key pair generated');\n\n return {\n publicKey: keypair.publicKey,\n privateKey: keypair.secretKey,\n };\n }\n\n if (keyType === 'ecdsa') {\n // Generate signing keypair\n const keypair = nacl.sign.keyPair();\n\n this.log('Signing key pair generated');\n\n return {\n publicKey: keypair.publicKey,\n privateKey: keypair.secretKey,\n };\n }\n\n throw new KeyError(\n `Unsupported key type for NaCl: ${keyType}. Use 'box' for encryption or 'sign' for signatures.`,\n this.adapterType,\n );\n } catch (error) {\n throw new KeyError(\n `Failed to generate NaCl key pair: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async importKey(\n key: string | Buffer,\n options?: ImportKeyOptions,\n ): Promise<Key> {\n try {\n this.log('Importing NaCl key');\n\n const encoding = this.options.encoding || 'base64';\n const keyData = typeof key === 'string' ? key : key.toString(encoding);\n const keyBytes = this.parseKey(keyData, encoding);\n\n const keyType = options?.type || 'public';\n const format = (options?.format || 'armored') as\n | 'armored'\n | 'binary'\n | 'pem'\n | 'der';\n\n // Validate key length\n const expectedLength =\n keyType === 'public'\n ? nacl.box.publicKeyLength\n : nacl.box.secretKeyLength;\n\n if (keyBytes.length !== expectedLength) {\n throw new InvalidKeyError(\n `NaCl ${keyType} key must be ${expectedLength} bytes`,\n this.adapterType,\n );\n }\n\n this.log('Key imported successfully');\n\n return {\n type: keyType as 'public' | 'private',\n format,\n data: keyData,\n algorithm: 'nacl',\n };\n } catch (error) {\n throw new InvalidKeyError(\n `Failed to import NaCl key: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n async exportKey(\n key: Key,\n options?: ExportKeyOptions,\n ): Promise<string | Buffer> {\n try {\n this.log('Exporting NaCl key');\n\n const format = options?.format || key.format || 'armored';\n // Use NaCl encoding from options or default\n const encoding = this.options.encoding || 'base64';\n\n if (typeof key.data === 'string') {\n if (format === 'binary') {\n return Buffer.from(key.data, encoding);\n }\n return key.data;\n }\n\n if (Buffer.isBuffer(key.data)) {\n if (format === 'armored') {\n return key.data.toString(encoding);\n }\n return key.data;\n }\n\n if (key.data instanceof Uint8Array) {\n if (format === 'binary') {\n return Buffer.from(key.data);\n }\n return this.formatKey(key.data, encoding);\n }\n\n throw new InvalidKeyError(\n 'Invalid key data format for export',\n this.adapterType,\n );\n } catch (error) {\n throw new KeyError(\n `Failed to export NaCl key: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Sign data with signing key\n */\n async sign(\n data: string | Buffer,\n options?: SignOptions,\n ): Promise<string | Buffer> {\n try {\n this.log('Signing data');\n\n // Get signing key\n let signingKey: Uint8Array;\n\n if (options?.privateKey) {\n signingKey = this.parseKey(\n options.privateKey,\n this.options.encoding || 'base64',\n );\n } else if (this.secretKey) {\n signingKey = this.secretKey;\n } else {\n throw new KeyError('No signing key available', this.adapterType);\n }\n\n // Validate key length for signing\n if (signingKey.length !== nacl.sign.secretKeyLength) {\n throw new InvalidKeyError(\n `NaCl signing key must be ${nacl.sign.secretKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Prepare message\n const message =\n typeof data === 'string' ? decodeUTF8(data) : new Uint8Array(data);\n\n // Sign the message\n const signed = nacl.sign(message, signingKey);\n\n this.log('Data signed successfully');\n\n if (typeof data === 'string') {\n return encodeBase64(signed);\n }\n\n return Buffer.from(signed);\n } catch (error) {\n throw new SignatureError(\n `Failed to sign data: ${(error as Error).message}`,\n this.adapterType,\n error,\n );\n }\n }\n\n /**\n * Verify signature\n */\n async verify(\n data: string | Buffer,\n signature: string | Buffer,\n options?: VerifyOptions,\n ): Promise<boolean> {\n try {\n this.log('Verifying signature');\n\n if (!options?.publicKey) {\n throw new KeyError(\n 'Public key required for signature verification',\n this.adapterType,\n );\n }\n\n // Get verification key\n const verificationKey = this.parseKey(\n options.publicKey,\n this.options.encoding || 'base64',\n );\n\n // Validate key length\n if (verificationKey.length !== nacl.sign.publicKeyLength) {\n throw new InvalidKeyError(\n `NaCl verification key must be ${nacl.sign.publicKeyLength} bytes`,\n this.adapterType,\n );\n }\n\n // Parse signed message\n const signedMessage =\n typeof signature === 'string'\n ? decodeBase64(signature)\n : new Uint8Array(signature);\n\n // Verify and open the signed message (extracts original message)\n const verified = nacl.sign.open(signedMessage, verificationKey);\n\n if (!verified) {\n this.log('Signature verification failed');\n return false;\n }\n\n // Compare extracted message with provided data\n const originalMessage =\n typeof data === 'string' ? decodeUTF8(data) : new Uint8Array(data);\n\n // Check if messages match\n if (verified.length !== originalMessage.length) {\n this.log('Signature verification failed: message mismatch');\n return false;\n }\n\n for (let i = 0; i < verified.length; i++) {\n if (verified[i] !== originalMessage[i]) {\n this.log('Signature verification failed: message mismatch');\n return false;\n }\n }\n\n this.log('Signature verified successfully');\n return true;\n } catch (error) {\n this.log('Signature verification failed', error);\n return false;\n }\n }\n\n async getCapabilities(): Promise<EncryptionCapabilities> {\n return {\n textEncryption: true,\n fileEncryption: true,\n bufferEncryption: true,\n streamEncryption: false,\n emailEncryption: false,\n signing: true,\n verification: true,\n keyGeneration: true,\n keyManagement: true,\n multipleRecipients: false,\n symmetricEncryption: true,\n asymmetricEncryption: true,\n };\n }\n}\n"],"names":["encrypted"],"mappings":"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"}