@alessiofrittoli/crypto-cipher 1.0.0 → 2.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/README.md CHANGED
@@ -89,7 +89,7 @@ pnpm i @alessiofrittoli/crypto-cipher
89
89
 
90
90
  #### Constants
91
91
 
92
- ##### `SALT_LENGTH`
92
+ ##### `Cipher.SALT_LENGTH`
93
93
 
94
94
  Defines the minimum, maximum, and default lengths for salt.
95
95
 
@@ -106,7 +106,7 @@ Defines the minimum, maximum, and default lengths for salt.
106
106
 
107
107
  ---
108
108
 
109
- ##### `IV_LENGTH`
109
+ ##### `Cipher.IV_LENGTH`
110
110
 
111
111
  Defines the minimum, maximum, and default lengths for initialization vectors (IV).
112
112
 
@@ -123,7 +123,7 @@ Defines the minimum, maximum, and default lengths for initialization vectors (IV
123
123
 
124
124
  ---
125
125
 
126
- ##### `AUTH_TAG_LENGTH`
126
+ ##### `Cipher.AUTH_TAG_LENGTH`
127
127
 
128
128
  Defines the minimum, maximum, and default lengths for authentication tags.
129
129
 
@@ -140,7 +140,7 @@ Defines the minimum, maximum, and default lengths for authentication tags.
140
140
 
141
141
  ---
142
142
 
143
- ##### `AAD_LENGTH`
143
+ ##### `Cipher.AAD_LENGTH`
144
144
 
145
145
  Defines the minimum, maximum, and default lengths for additional authenticated data (AAD).
146
146
 
@@ -157,23 +157,23 @@ Defines the minimum, maximum, and default lengths for additional authenticated d
157
157
 
158
158
  ---
159
159
 
160
- ##### `DEFAULT_ALGORITHM`
160
+ ##### `Cipher.DEFAULT_ALGORITHM`
161
161
 
162
162
  Specifies default AES algorithms for buffer and stream operations.
163
163
 
164
164
  <details>
165
165
  <summary>Properties</summary>
166
166
 
167
- | Operation | Algorithm |
168
- |------------|--------------|
169
- | `buffer` | `aes-256-gcm` |
170
- | `stream` | `aes-256-cbc` |
167
+ | Operation | Algorithm | Description |
168
+ |------------|--------------|-------------|
169
+ | `buffer` | `aes-256-gcm` | Default algorithm used for buffer data encryption/decryption |
170
+ | `stream` | `aes-256-cbc` | Default algorithm used for stream encryption/decryption |
171
171
 
172
172
  </details>
173
173
 
174
174
  ---
175
175
 
176
- ##### `ALGORITHMS`
176
+ ##### `Cipher.ALGORITHMS`
177
177
 
178
178
  Supported AES algorithms:
179
179
 
@@ -299,16 +299,18 @@ Encrypts a `Readable` stream to a `Writable` stream.
299
299
 
300
300
  <summary>Returns</summary>
301
301
 
302
- Type: `Promise<void>`
302
+ Type: `Cph.Stream.Symmetric.EncryptReturnType`
303
303
 
304
- - A new Promise that resolves when the stream encryption is complete.
304
+ - An object containing:
305
+ - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.
306
+ - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
305
307
 
306
308
  </details>
307
309
 
308
310
  ---
309
311
 
310
312
  - See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.
311
- - See [`Cph.Stream.Symmetric.EncryptOptions`](#cphstreamsymmetricencryptoptions) for more informations about additional encryption options.
313
+ - See [`Cph.Stream.Symmetric.EncryptOptions`](#cphstreamsymmetricencryptoptions) for more informations about encryption options.
312
314
  - See [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption) examples.
313
315
  - See [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption) examples.
314
316
 
@@ -335,16 +337,18 @@ Decrypts a `Readable` stream to a `Writable` stream.
335
337
 
336
338
  <summary>Returns</summary>
337
339
 
338
- Type: `Promise<void>`
340
+ Type: `Promise<Cph.Stream.Symmetric.DecryptReturnType>`
339
341
 
340
- - A new Promise that resolves when the stream decryption is complete.
342
+ - A new Promise that resolves when Key IV extraction completes returning an object containing:
343
+ - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
344
+ - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
341
345
 
342
346
  </details>
343
347
 
344
348
  ---
345
349
 
346
350
  - See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.
347
- - See [`Cph.Stream.Symmetric.DecryptOptions`](#cphstreamsymmetricdecryptoptions) for more informations about additional decryption options.
351
+ - See [`Cph.Stream.Symmetric.DecryptOptions`](#cphstreamsymmetricdecryptoptions) for more informations about decryption options.
348
352
  - See [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption) examples.
349
353
  - See [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption) examples.
350
354
 
@@ -372,16 +376,18 @@ Encrypts a stream using hybrid encryption (symmetric + RSA).
372
376
 
373
377
  <summary>Returns</summary>
374
378
 
375
- Type: `Promise<void>`
379
+ Type: `Cph.Stream.Hybrid.EncryptReturnType`
376
380
 
377
- - A new Promise that resolves when hybrid encryption is complete.
381
+ - An object containing:
382
+ - a new instance of `cipher` allowing you to add listeners to the `cipher` encryption process.
383
+ - the actual `encrypt` callback that must be called and awaited to start the encryption process.
378
384
 
379
385
  </details>
380
386
 
381
387
  ---
382
388
 
383
389
  - See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.
384
- - See [`Cph.Stream.Hybrid.EncryptOptions`](#cphstreamhybridencryptoptions) for more informations about additional encryption options.
390
+ - See [`Cph.Stream.Hybrid.EncryptOptions`](#cphstreamhybridencryptoptions) for more informations about encryption options.
385
391
  - See [In-memory data stream with hybrid encryption/decryption](#in-memory-data-stream-with-hybrid-encryptiondecryption) examples.
386
392
  - See [File based data stream with hybrid encryption/decryption](#file-based-data-stream-with-hybrid-encryptiondecryption) examples.
387
393
 
@@ -408,9 +414,11 @@ Decrypts a stream using hybrid decryption (symmetric + RSA).
408
414
 
409
415
  <summary>Returns</summary>
410
416
 
411
- Type: `Promise<void>`
417
+ Type: `Promise<Cph.Stream.Hybrid.DecryptReturnType>`
412
418
 
413
- - A new Promise that resolves when hybrid decryption is complete.
419
+ - A new Promise that resolves when Key IV extraction completes returning an object containing:
420
+ - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
421
+ - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
414
422
 
415
423
  </details>
416
424
 
@@ -432,13 +440,13 @@ This module supports different input data types and it uses the [`coerceToUint8A
432
440
 
433
441
  ---
434
442
 
435
- ##### `CBCTypes`
443
+ ##### `Cph.CBCTypes`
436
444
 
437
445
  Cipher CBC algorithm types.
438
446
 
439
447
  ---
440
448
 
441
- ##### `AesAlgorithm`
449
+ ##### `Cph.AesAlgorithm`
442
450
 
443
451
  Supported AES algorithm types.
444
452
 
@@ -452,9 +460,9 @@ Common options in encryption/decryption processes.
452
460
 
453
461
  <summary>Type parameters</summary>
454
462
 
455
- | Parameter | Default | Description |
456
- |-------------|----------------|-------------|
457
- | `T` | `AesAlgorithm` | Accepted algorithm in `Cph.Options`. This is usefull to constraint specifc algorithms. |
463
+ | Parameter | Default | Description |
464
+ |-----------|----------------|-------------|
465
+ | `T` | `Cph.AesAlgorithm` | Accepted algorithm in `Cph.Options`. This is usefull to constraint specifc algorithms. |
458
466
 
459
467
  </details>
460
468
 
@@ -496,6 +504,23 @@ Stream symmetric encryption options.
496
504
 
497
505
  ---
498
506
 
507
+ ##### `Cph.Stream.Symmetric.EncryptReturnType`
508
+
509
+ Returnign object from `Cipher.streamEncrypt()` method.
510
+
511
+ <details>
512
+
513
+ <summary>Properties</summary>
514
+
515
+ | Property | Type | Description |
516
+ |----------|----------|-------------|
517
+ | `cipher` | `crypto.Cipher` | The `crypto.Cipher` instance. |
518
+ | `encrypt` | `() => Promise<void>` | The actual `encrypt` callback that must be called and awaited in order to start the encryption process. |
519
+
520
+ </details>
521
+
522
+ ---
523
+
499
524
  ##### `Cph.Stream.Symmetric.DecryptOptions`
500
525
 
501
526
  Stream symmetric decryption options.
@@ -515,6 +540,23 @@ Stream symmetric decryption options.
515
540
 
516
541
  ---
517
542
 
543
+ ##### `Cph.Stream.Symmetric.DecryptReturnType`
544
+
545
+ Returnign object from awaited `Cipher.streamDecrypt()` method.
546
+
547
+ <details>
548
+
549
+ <summary>Properties</summary>
550
+
551
+ | Property | Type | Description |
552
+ |----------|----------|-------------|
553
+ | `decipher` | `crypto.Decipher` | The `crypto.Decipher` instance. |
554
+ | `decrypt` | `() => Promise<void>` | The actual `decrypt` callback that must be called and awaited in order to start the decryption process. |
555
+
556
+ </details>
557
+
558
+ ---
559
+
518
560
  ##### `Cph.Stream.Hybrid.EncryptOptions`
519
561
 
520
562
  Stream hybrid encryption options.
@@ -523,6 +565,14 @@ Stream hybrid encryption options.
523
565
 
524
566
  ---
525
567
 
568
+ ##### `Cph.Stream.Hybrid.EncryptReturnType`
569
+
570
+ Returnign object from `Cipher.hybridEncrypt()` method.
571
+
572
+ - Alias for [`Cph.Stream.Symmetric.EncryptReturnType`](#cphstreamsymmetricencryptreturntype)
573
+
574
+ ---
575
+
526
576
  ##### `Cph.Stream.Hybrid.DecryptOptions`
527
577
 
528
578
  Stream hybrid decryption options.
@@ -541,6 +591,14 @@ Stream hybrid decryption options.
541
591
 
542
592
  ---
543
593
 
594
+ ##### `Cph.Stream.Hybrid.DecryptReturnType`
595
+
596
+ Returnign object from awaited `Cipher.hybridDecrypt()` method.
597
+
598
+ - Alias for [`Cph.Stream.Symmetric.DecryptReturnType`](#cphstreamsymmetricdecryptreturntype)
599
+
600
+ ---
601
+
544
602
  ### Examples
545
603
 
546
604
  #### Importing the library
@@ -609,6 +667,7 @@ const routeHandler = () => {
609
667
  } )
610
668
 
611
669
  Cipher.streamEncrypt( password, { input, output } )
670
+ .encrypt()
612
671
 
613
672
  return (
614
673
  // encrypted stream
@@ -664,7 +723,9 @@ const routeHandler = () => (
664
723
  },
665
724
  } )
666
725
 
667
- Cipher.streamDecrypt( password, { input, output } )
726
+ const { decrypt } = await Cipher.streamDecrypt( password, { input, output } )
727
+
728
+ decrypt()
668
729
 
669
730
  return (
670
731
  // decrypted stream
@@ -729,12 +790,13 @@ const output = new Writable( {
729
790
  }
730
791
  } )
731
792
 
732
- await Cipher.hybridEncrypt( password, {
793
+ const { encrypt } = Cipher.hybridEncrypt( password, {
733
794
  key : keyPair.publicKey,
734
795
  padding : crypto.constants.RSA_PKCS1_OAEP_PADDING,
735
796
  oaepHash : 'SHA-256',
736
797
  }, { input, output } )
737
798
 
799
+ await encrypt()
738
800
  ```
739
801
 
740
802
  ---
@@ -762,7 +824,7 @@ const output = new Writable( {
762
824
  },
763
825
  } )
764
826
 
765
- await Cipher.hybridDecrypt(
827
+ const { decrypt } = await Cipher.hybridDecrypt(
766
828
  {
767
829
  key : keyPair.privateKey,
768
830
  passphrase: password, // optional passhrase (required if set while generating keypair).
@@ -771,6 +833,8 @@ await Cipher.hybridDecrypt(
771
833
  }, { input, output, rsaKeyLength }
772
834
  )
773
835
 
836
+ await decrypt()
837
+
774
838
  console.log( Buffer.concat( chunks ).toString() ) // Outputs: 'my top-secret data'
775
839
  ```
776
840
 
@@ -793,6 +857,7 @@ const input = fs.createReadStream( 'my-very-large-top-secret-file.pdf' )
793
857
  const output = fs.createWriteStream( 'my-very-large-top-secret-file.encrypted' )
794
858
  // encrypt
795
859
  await Cipher.streamEncrypt( password, { input, output } )
860
+ .encrypt()
796
861
  ```
797
862
 
798
863
  ---
@@ -809,7 +874,8 @@ const input = fs.createReadStream( 'my-very-large-top-secret-file.encrypted' )
809
874
  // output where decrypted data is written
810
875
  const output = fs.createWriteStream( 'my-very-large-top-secret-file-decrypted.pdf' )
811
876
  // decrypt
812
- await Cipher.streamDecrypt( password, { input, output } )
877
+ const { decrypt } = await Cipher.streamDecrypt( password, { input, output } )
878
+ await decrypt()
813
879
  ```
814
880
 
815
881
  ---
@@ -852,11 +918,12 @@ const input = fs.createReadStream( 'my-very-large-top-secret-file.pdf' )
852
918
  // output where encrypted data is written
853
919
  const output = fs.createWriteStream( 'my-very-large-top-secret-file.encrypted' )
854
920
  // encrypt
855
- await Cipher.hybridEncrypt( password, {
921
+ const { encrypt } = Cipher.hybridEncrypt( password, {
856
922
  key : keyPair.publicKey,
857
923
  padding : crypto.constants.RSA_PKCS1_OAEP_PADDING,
858
924
  oaepHash : 'SHA-256',
859
925
  }, { input, output } )
926
+ await encrypt()
860
927
  ```
861
928
 
862
929
  ---
@@ -873,7 +940,7 @@ const input = fs.createReadStream( 'my-very-large-top-secret-file.encrypted' )
873
940
  // output where decrypted data is written
874
941
  const output = fs.createWriteStream( 'my-very-large-top-secret-file-decrypted.pdf' )
875
942
  // decrypt
876
- await Cipher.hybridDecrypt(
943
+ const { decrypt } = await Cipher.hybridDecrypt(
877
944
  {
878
945
  key : keyPair.privateKey,
879
946
  passphrase: password, // optional passhrase (required if set while generating keypair).
@@ -923,21 +990,19 @@ Run all the defined test suites by running the following:
923
990
  # Run tests and watch file changes.
924
991
  pnpm test:watch
925
992
 
926
- # Run tests and watch file changes with jest-environment-jsdom.
927
- pnpm test:jsdom
928
-
929
993
  # Run tests in a CI environment.
930
994
  pnpm test:ci
931
-
932
- # Run tests in a CI environment with jest-environment-jsdom.
933
- pnpm test:ci:jsdom
934
995
  ```
935
996
 
936
997
  You can eventually run specific suits like so:
937
998
 
938
999
  ```bash
939
- pnpm test:jest
940
- pnpm test:jest:jsdom
1000
+ pnpm test:buffer-in-memory
1001
+ pnpm test:file-symmetric
1002
+ pnpm test:file-hybrid
1003
+ pnpm test:stream-symmetric
1004
+ pnpm test:stream-hybrid
1005
+ pnpm test:misc
941
1006
  ```
942
1007
 
943
1008
  Run tests with coverage.
package/dist/index.d.mts CHANGED
@@ -80,9 +80,11 @@ declare class Cipher {
80
80
  *
81
81
  * @param secret The secret key used to encrypt the `data`.
82
82
  * @param options Additional options.
83
- * @returns A new Promise that resolves `void` once stream is completed.
83
+ * @returns An object containing:
84
+ * - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.
85
+ * - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
84
86
  */
85
- static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Promise<void>;
87
+ static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Cph.Stream.Symmetric.EncryptReturnType;
86
88
  /**
87
89
  * Decrypt a `Readable` to a `Writable` Stream.
88
90
  *
@@ -90,9 +92,11 @@ declare class Cipher {
90
92
  *
91
93
  * @param secret The secret key used to encrypt the `data`.
92
94
  * @param options Additional options.
93
- * @returns A new Promise that resolves `void` once stream is completed.
95
+ * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
96
+ * - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
97
+ * - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
94
98
  */
95
- static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<void>;
99
+ static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<Cph.Stream.Symmetric.DecryptReturnType>;
96
100
  /**
97
101
  * Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.
98
102
  *
@@ -101,9 +105,11 @@ declare class Cipher {
101
105
  * @param secret The secret key used to encrypt the stream.
102
106
  * @param publicKey The RSA public key used to encrypt the symmetric key.
103
107
  * @param options Options for the stream encryption.
104
- * @returns A new Promise that resolves `void` once stream is completed.
108
+ * @returns An object containing:
109
+ * - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.
110
+ * - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
105
111
  */
106
- static hybridEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Promise<void>;
112
+ static hybridEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Cph.Stream.Hybrid.EncryptReturnType;
107
113
  /**
108
114
  * Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.
109
115
  *
@@ -111,9 +117,11 @@ declare class Cipher {
111
117
  *
112
118
  * @param privateKey The RSA private key used to decrypt the symmetric key.
113
119
  * @param options Options for the stream decryption.
114
- * @returns A new Promise that resolves `void` once stream is completed.
120
+ * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
121
+ * - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
122
+ * - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
115
123
  */
116
- static hybridDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<void>;
124
+ static hybridDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<Cph.Stream.Hybrid.DecryptReturnType>;
117
125
  /**
118
126
  * Handle pipe flow to encrypt a Stream.
119
127
  *
@@ -148,7 +156,7 @@ declare class Cipher {
148
156
  options: T;
149
157
  Key: Buffer<ArrayBufferLike>;
150
158
  IV: Buffer<ArrayBufferLike>;
151
- AAD: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>;
159
+ AAD: Buffer<ArrayBufferLike> | Uint8Array<ArrayBufferLike>;
152
160
  salt: Buffer<ArrayBufferLike>;
153
161
  };
154
162
  /**
package/dist/index.d.ts CHANGED
@@ -80,9 +80,11 @@ declare class Cipher {
80
80
  *
81
81
  * @param secret The secret key used to encrypt the `data`.
82
82
  * @param options Additional options.
83
- * @returns A new Promise that resolves `void` once stream is completed.
83
+ * @returns An object containing:
84
+ * - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.
85
+ * - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
84
86
  */
85
- static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Promise<void>;
87
+ static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Cph.Stream.Symmetric.EncryptReturnType;
86
88
  /**
87
89
  * Decrypt a `Readable` to a `Writable` Stream.
88
90
  *
@@ -90,9 +92,11 @@ declare class Cipher {
90
92
  *
91
93
  * @param secret The secret key used to encrypt the `data`.
92
94
  * @param options Additional options.
93
- * @returns A new Promise that resolves `void` once stream is completed.
95
+ * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
96
+ * - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
97
+ * - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
94
98
  */
95
- static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<void>;
99
+ static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<Cph.Stream.Symmetric.DecryptReturnType>;
96
100
  /**
97
101
  * Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.
98
102
  *
@@ -101,9 +105,11 @@ declare class Cipher {
101
105
  * @param secret The secret key used to encrypt the stream.
102
106
  * @param publicKey The RSA public key used to encrypt the symmetric key.
103
107
  * @param options Options for the stream encryption.
104
- * @returns A new Promise that resolves `void` once stream is completed.
108
+ * @returns An object containing:
109
+ * - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.
110
+ * - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
105
111
  */
106
- static hybridEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Promise<void>;
112
+ static hybridEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Cph.Stream.Hybrid.EncryptReturnType;
107
113
  /**
108
114
  * Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.
109
115
  *
@@ -111,9 +117,11 @@ declare class Cipher {
111
117
  *
112
118
  * @param privateKey The RSA private key used to decrypt the symmetric key.
113
119
  * @param options Options for the stream decryption.
114
- * @returns A new Promise that resolves `void` once stream is completed.
120
+ * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
121
+ * - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.
122
+ * - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
115
123
  */
116
- static hybridDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<void>;
124
+ static hybridDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<Cph.Stream.Hybrid.DecryptReturnType>;
117
125
  /**
118
126
  * Handle pipe flow to encrypt a Stream.
119
127
  *
@@ -148,7 +156,7 @@ declare class Cipher {
148
156
  options: T;
149
157
  Key: Buffer<ArrayBufferLike>;
150
158
  IV: Buffer<ArrayBufferLike>;
151
- AAD: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>;
159
+ AAD: Buffer<ArrayBufferLike> | Uint8Array<ArrayBufferLike>;
152
160
  salt: Buffer<ArrayBufferLike>;
153
161
  };
154
162
  /**
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- 'use strict';var u=require('crypto'),stream=require('stream'),coercion=require('@alessiofrittoli/crypto-buffer/coercion');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var u__default=/*#__PURE__*/_interopDefault(u);var t=class t{static encrypt(a,e,o={}){let r=coercion.coerceToUint8Array(a),{salt:n,Key:c,IV:i,AAD:p,options:{algorithm:s,authTag:h}}=t.newKeyIV(e,o);if(t.isCBC(s)){let d=u__default.default.createCipheriv(s,c,i),f=Buffer.concat([d.update(r),d.final()]);return Buffer.concat([n,i,f])}let y=u__default.default.createCipheriv(s,c,i,{authTagLength:h});t.isCCM(s)&&y.setAAD(p,{plaintextLength:r.length}),(t.isGCM(s)||t.isOCB(s))&&y.setAAD(p);let m=Buffer.concat([y.update(r),y.final()]),l=y.getAuthTag();return Buffer.concat([n,i,p,l,m])}static decrypt(a,e,o={}){let r=coercion.coerceToUint8Array(a),n=coercion.coerceToUint8Array(e),c=t.resolveOptions(o),{algorithm:i}=c,p=r.subarray(0,c.salt);r=r.subarray(c.salt);let s=r.subarray(0,c.iv);r=r.subarray(c.iv);let h=u__default.default.scryptSync(n,p,c.length);if(t.isCBC(i)){let T=u__default.default.createDecipheriv(c.algorithm,h,s);return Buffer.concat([T.update(r),T.final()])}let y=c.aadLength,m=c.authTag,l=r.subarray(0,y);r=r.subarray(y);let d=r.subarray(0,m);r=r.subarray(m);let f=u__default.default.createDecipheriv(i,h,s,{authTagLength:m});return t.isCCM(i)&&f.setAAD(l,{plaintextLength:r.length}),(t.isGCM(i)||t.isOCB(i))&&f.setAAD(l),f.setAuthTag(d),Buffer.concat([f.update(r),f.final()])}static streamEncrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:o,IV:r,options:{input:n,output:c,algorithm:i,salt:p,iv:s,authTag:h}}=t.newKeyIV(a,e),y=t.encrypt(Buffer.concat([o,r]),a,{algorithm:i,salt:p,iv:s,authTag:h});return t.stream({Key:o,IV:r,input:n,output:c,encryptedKey:y,algorithm:i})}static streamDecrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:r,algorithm:n,salt:c,iv:i,authTag:p,length:s}=t.resolveOptions(e),h=s+i+c+i+p;return t.extractKeyIV(o,h).then(([y,m])=>{if(m.errored)throw m.errored;let l=t.decrypt(y,a,{algorithm:n,salt:c,iv:i,authTag:p});return t.decipherStream({KeyIV:l,length:s,input:m,output:r,algorithm:n})})}static hybridEncrypt(a,e,o){o.algorithm||(o.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:r,IV:n,options:{algorithm:c,input:i,output:p}}=t.newKeyIV(a,o),s=u__default.default.publicEncrypt(e,Buffer.concat([r,n]));return t.stream({Key:r,IV:n,input:i,output:p,encryptedKey:s,algorithm:c})}static hybridDecrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:r,algorithm:n,length:c,rsaKeyLength:i}=t.resolveOptions(e);return t.extractKeyIV(o,i).then(([p,s])=>{if(s.errored)throw s.errored;let h=u__default.default.privateDecrypt(a,p);return t.decipherStream({KeyIV:h,length:c,input:s,output:r,algorithm:n})})}static stream(a){let{Key:e,IV:o,encryptedKey:r,input:n,output:c,algorithm:i}=a;return new Promise((p,s)=>{let h=u__default.default.createCipheriv(i,e,o);h.on("error",s),n.on("error",s),c.on("error",s),c.on("finish",p),c.write(r),n.pipe(h).pipe(c);})}static decipherStream(a){let{KeyIV:e,length:o,algorithm:r,input:n,output:c}=a;return new Promise((i,p)=>{let s=e.subarray(0,o),h=e.subarray(o),y=u__default.default.createDecipheriv(r,s,h);y.on("error",p),n.on("error",p),c.on("error",p),c.on("finish",i),n.pipe(y).pipe(c);})}static extractKeyIV(a,e){return new Promise((o,r)=>{let n=Buffer.alloc(0),c=0,i=false,p=new stream.Transform({async transform(s,h,y){if(n.length<e&&(n=Buffer.concat([n,s])),c+=s.length,n.length>e){let m=Math.max(0,n.length-e);n=n.subarray(0,e);let l=s.subarray(m*-1);return i||(o([n,this]),i=true),this.push(l,h),y()}return c>e&&(i||(o([n,this]),i=true),this.push(s,h)),y()},final(s){return n.length<e?s(new Error("The extracted KeyIV length is less than the expected length.")):s()}});p.on("error",r),a.on("error",s=>{p.destroy(s),r(s);}),a.pipe(p);})}static newKeyIV(a,e={}){let o=coercion.coerceToUint8Array(a),r=t.resolveOptions(e),n=u__default.default.randomBytes(r.salt),c=u__default.default.scryptSync(o,n,r.length),i=u__default.default.randomBytes(r.iv),p=r.aad||u__default.default.scryptSync(c,n,r.aadLength);return {options:r,Key:c,IV:i,AAD:p,salt:n}}static resolveOptions(a={}){let e={...a};e.aad&&(e.aad=coercion.coerceToUint8Array(e.aad)),e.salt||(e.salt=t.SALT_LENGTH.default),e.authTag||(e.authTag=t.AUTH_TAG_LENGTH.default),e.aadLength=e.aad?.length||e.aadLength||t.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,t.SALT_LENGTH.min),t.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,t.AUTH_TAG_LENGTH.min),t.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,t.AAD_LENGTH.min),t.AAD_LENGTH.max));let{keyLength:o,algorithm:r}=t.getKeyLength(a.algorithm);return e.algorithm=r,e.length=o,e.iv=t.getIVLength(r,a),e}static getIVLength(a=t.DEFAULT_ALGORITHM.buffer,e={}){switch(a){case "aes-128-ccm":case "aes-128-ocb":case "aes-192-ccm":case "aes-192-ocb":case "aes-256-ccm":case "aes-256-ocb":return 8;case "chacha20-poly1305":return 12;default:return Math.min(Math.max(e.iv||t.IV_LENGTH.default,t.IV_LENGTH.min),t.IV_LENGTH.max)}}static getKeyLength(a=t.DEFAULT_ALGORITHM.buffer){switch(a){case "chacha20-poly1305":return {algorithm:a,keyLength:256/8};case "aes-128-cbc":case "aes-128-ccm":case "aes-128-gcm":case "aes-128-ocb":return {algorithm:a,keyLength:128/8};case "aes-192-cbc":case "aes-192-ccm":case "aes-192-gcm":case "aes-192-ocb":return {algorithm:a,keyLength:192/8};case "aes-256-cbc":case "aes-256-ccm":case "aes-256-gcm":case "aes-256-ocb":default:return {algorithm:a,keyLength:256/8}}}static isGCM(a){return a==="aes-128-gcm"||a==="aes-192-gcm"||a==="aes-256-gcm"}static isCCM(a){return a==="aes-128-ccm"||a==="aes-192-ccm"||a==="aes-256-ccm"||a==="chacha20-poly1305"}static isOCB(a){return a==="aes-128-ocb"||a==="aes-192-ocb"||a==="aes-256-ocb"}static isCBC(a){return a==="aes-128-cbc"||a==="aes-192-cbc"||a==="aes-256-cbc"}};t.SALT_LENGTH={min:16,max:64,default:32},t.IV_LENGTH={min:8,max:32,default:16},t.AUTH_TAG_LENGTH={min:4,max:16,default:16},t.AAD_LENGTH={min:16,max:128,default:32},t.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},t.ALGORITHMS=["aes-128-cbc","aes-128-ccm","aes-128-gcm","aes-128-ocb","aes-192-cbc","aes-192-ccm","aes-192-gcm","aes-192-ocb","aes-256-cbc","aes-256-ccm","aes-256-gcm","aes-256-ocb","chacha20-poly1305"];var A=t;exports.Cipher=A;
1
+ 'use strict';var m=require('crypto'),stream=require('stream'),coercion=require('@alessiofrittoli/crypto-buffer/coercion');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var m__default=/*#__PURE__*/_interopDefault(m);var t=class t{static encrypt(r,e,o={}){let a=coercion.coerceToUint8Array(r),{salt:c,Key:s,IV:n,AAD:p,options:{algorithm:i,authTag:h}}=t.newKeyIV(e,o);if(t.isCBC(i)){let T=m__default.default.createCipheriv(i,s,n),d=Buffer.concat([T.update(a),T.final()]);return Buffer.concat([c,n,d])}let y=m__default.default.createCipheriv(i,s,n,{authTagLength:h});t.isCCM(i)&&y.setAAD(p,{plaintextLength:a.length}),(t.isGCM(i)||t.isOCB(i))&&y.setAAD(p);let u=Buffer.concat([y.update(a),y.final()]),l=y.getAuthTag();return Buffer.concat([c,n,p,l,u])}static decrypt(r,e,o={}){let a=coercion.coerceToUint8Array(r),c=coercion.coerceToUint8Array(e),s=t.resolveOptions(o),{algorithm:n}=s,p=a.subarray(0,s.salt);a=a.subarray(s.salt);let i=a.subarray(0,s.iv);a=a.subarray(s.iv);let h=m__default.default.scryptSync(c,p,s.length);if(t.isCBC(n)){let f=m__default.default.createDecipheriv(s.algorithm,h,i);return Buffer.concat([f.update(a),f.final()])}let y=s.aadLength,u=s.authTag,l=a.subarray(0,y);a=a.subarray(y);let T=a.subarray(0,u);a=a.subarray(u);let d=m__default.default.createDecipheriv(n,h,i,{authTagLength:u});return t.isCCM(n)&&d.setAAD(l,{plaintextLength:a.length}),(t.isGCM(n)||t.isOCB(n))&&d.setAAD(l),d.setAuthTag(T),Buffer.concat([d.update(a),d.final()])}static streamEncrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:o,IV:a,options:{input:c,output:s,algorithm:n,salt:p,iv:i,authTag:h}}=t.newKeyIV(r,e),y=t.encrypt(Buffer.concat([o,a]),r,{algorithm:n,salt:p,iv:i,authTag:h}),u=m__default.default.createCipheriv(n,o,a);return {cipher:u,encrypt:()=>t.stream({cipher:u,input:c,output:s,encryptedKey:y})}}static streamDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,salt:s,iv:n,authTag:p,length:i}=t.resolveOptions(e),h=i+n+s+n+p;return t.extractKeyIV(o,h).then(([y,u])=>{if(u.errored)throw u.errored;let l=t.decrypt(y,r,{algorithm:c,salt:s,iv:n,authTag:p}),T=l.subarray(0,i),d=l.subarray(i),f=m__default.default.createDecipheriv(c,T,d);return {decipher:f,decrypt:()=>t.decipherStream({decipher:f,input:u,output:a})}})}static hybridEncrypt(r,e,o){o.algorithm||(o.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:a,IV:c,options:{algorithm:s,input:n,output:p}}=t.newKeyIV(r,o),i=m__default.default.publicEncrypt(e,Buffer.concat([a,c])),h=m__default.default.createCipheriv(s,a,c);return {cipher:h,encrypt:()=>t.stream({cipher:h,input:n,output:p,encryptedKey:i})}}static hybridDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,length:s,rsaKeyLength:n}=t.resolveOptions(e);return t.extractKeyIV(o,n).then(([p,i])=>{let h=m__default.default.privateDecrypt(r,p),y=h.subarray(0,s),u=h.subarray(s),l=m__default.default.createDecipheriv(c,y,u);return {decipher:l,decrypt:()=>t.decipherStream({decipher:l,input:i,output:a})}})}static stream(r){let{cipher:e,encryptedKey:o,input:a,output:c}=r;return new Promise((s,n)=>{e.on("error",n),a.on("error",n),c.on("error",n),c.on("finish",s),c.write(o),a.pipe(e).pipe(c);})}static decipherStream(r){let{decipher:e,input:o,output:a}=r;return new Promise((c,s)=>{e.on("error",s),o.on("error",s),a.on("error",s),a.on("finish",c),o.pipe(e).pipe(a);})}static extractKeyIV(r,e){return new Promise((o,a)=>{let c=Buffer.alloc(0),s=0,n=false,p=new stream.Transform({async transform(i,h,y){if(c.length<e&&(c=Buffer.concat([c,i])),s+=i.length,c.length>e){let u=Math.max(0,c.length-e);c=c.subarray(0,e);let l=i.subarray(u*-1);return n||(o([c,this]),n=true),this.push(l,h),y()}return s>e&&(n||(o([c,this]),n=true),this.push(i,h)),y()},final(i){return c.length<e?i(new Error("The extracted KeyIV length is less than the expected length.")):i()}});p.on("error",a),r.on("error",i=>{p.destroy(i),a(i);}),r.pipe(p);})}static newKeyIV(r,e={}){let o=coercion.coerceToUint8Array(r),a=t.resolveOptions(e),c=m__default.default.randomBytes(a.salt),s=m__default.default.scryptSync(o,c,a.length),n=m__default.default.randomBytes(a.iv),p=a.aad||m__default.default.scryptSync(s,c,a.aadLength);return {options:a,Key:s,IV:n,AAD:p,salt:c}}static resolveOptions(r={}){let e={...r};e.aad&&(e.aad=coercion.coerceToUint8Array(e.aad)),e.salt||(e.salt=t.SALT_LENGTH.default),e.authTag||(e.authTag=t.AUTH_TAG_LENGTH.default),e.aadLength=e.aad?.length||e.aadLength||t.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,t.SALT_LENGTH.min),t.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,t.AUTH_TAG_LENGTH.min),t.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,t.AAD_LENGTH.min),t.AAD_LENGTH.max));let{keyLength:o,algorithm:a}=t.getKeyLength(r.algorithm);return e.algorithm=a,e.length=o,e.iv=t.getIVLength(a,r),e}static getIVLength(r=t.DEFAULT_ALGORITHM.buffer,e={}){switch(r){case "aes-128-ccm":case "aes-128-ocb":case "aes-192-ccm":case "aes-192-ocb":case "aes-256-ccm":case "aes-256-ocb":return 8;case "chacha20-poly1305":return 12;default:return Math.min(Math.max(e.iv||t.IV_LENGTH.default,t.IV_LENGTH.min),t.IV_LENGTH.max)}}static getKeyLength(r=t.DEFAULT_ALGORITHM.buffer){switch(r){case "chacha20-poly1305":return {algorithm:r,keyLength:256/8};case "aes-128-cbc":case "aes-128-ccm":case "aes-128-gcm":case "aes-128-ocb":return {algorithm:r,keyLength:128/8};case "aes-192-cbc":case "aes-192-ccm":case "aes-192-gcm":case "aes-192-ocb":return {algorithm:r,keyLength:192/8};case "aes-256-cbc":case "aes-256-ccm":case "aes-256-gcm":case "aes-256-ocb":default:return {algorithm:r,keyLength:256/8}}}static isGCM(r){return r==="aes-128-gcm"||r==="aes-192-gcm"||r==="aes-256-gcm"}static isCCM(r){return r==="aes-128-ccm"||r==="aes-192-ccm"||r==="aes-256-ccm"||r==="chacha20-poly1305"}static isOCB(r){return r==="aes-128-ocb"||r==="aes-192-ocb"||r==="aes-256-ocb"}static isCBC(r){return r==="aes-128-cbc"||r==="aes-192-cbc"||r==="aes-256-cbc"}};t.SALT_LENGTH={min:16,max:64,default:32},t.IV_LENGTH={min:8,max:32,default:16},t.AUTH_TAG_LENGTH={min:4,max:16,default:16},t.AAD_LENGTH={min:16,max:128,default:32},t.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},t.ALGORITHMS=["aes-128-cbc","aes-128-ccm","aes-128-gcm","aes-128-ocb","aes-192-cbc","aes-192-ccm","aes-192-gcm","aes-192-ocb","aes-256-cbc","aes-256-ccm","aes-256-gcm","aes-256-ocb","chacha20-poly1305"];var A=t;exports.Cipher=A;//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["_Cipher","data","secret","options","_data","coerceToUint8Array","salt","Key","IV","AAD","algorithm","authTagLength","cipher","crypto","encrypted","authTag","_secret","_options","decipher","AADLength","input","output","iv","encryptedKey","length","keyIvLength","encryptedKeyIV","KeyIV","publicKey","privateKey","rsaKeyLength","resolve","reject","keyLength","bytesRead","resolved","transform","Transform","chunk","encoding","callback","bytesLoss","subchunk","error","Cipher"],"mappings":"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","file":"index.js","sourcesContent":["import crypto from 'crypto'\nimport { Transform } from 'stream'\nimport type { Readable, Writable } from 'stream'\nimport { coerceToUint8Array, type CoerceToUint8ArrayInput } from '@alessiofrittoli/crypto-buffer/coercion'\n\nimport type { Cph } from './types'\n\n\n\n/**\n * INTERNAL USE ONLY\n */\ninterface StreamEncryptOptions\n{\n\tcipher\t\t: crypto.Cipher\n\tencryptedKey: Buffer\n\tinput\t\t: Readable\n\toutput\t\t: Writable\n}\n\n\n/**\n * INTERNAL USE ONLY\n */\ninterface StreamDecryptOptions\n{\n\tdecipher\t: crypto.Decipher\n\tinput\t\t: Readable\n\toutput\t\t: Writable\n}\n\n\n/**\n * Utility class for AES encryption and decryption following [NIST SP 800-38D](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf) standard reccomendations.\n */\nexport class Cipher\n{\n\t/**\n\t * Cipher default `salt` lengths.\n\t */\n\tstatic readonly SALT_LENGTH = {\n\t\tmin\t\t: 16,\n\t\tmax\t\t: 64,\n\t\tdefault\t: 32,\n\t} as const\n\n\n\t/**\n\t * Cipher default `IV` lengths.\n\t */\n\tstatic readonly IV_LENGTH = {\n\t\tmin\t\t: 8,\n\t\tmax\t\t: 32,\n\t\tdefault\t: 16,\n\t} as const\n\n\n\t/**\n\t * Cipher default `Auth Tag` lengths.\n\t */\n\tstatic readonly AUTH_TAG_LENGTH = {\n\t\tmin\t\t: 4,\n\t\tmax\t\t: 16,\n\t\tdefault\t: 16,\n\t} as const\n\t\n\t\n\t/**\n\t * Cipher default `Additional Authenticated Data` lengths.\n\t */\n\tstatic readonly AAD_LENGTH = {\n\t\tmin\t\t: 16,\n\t\tmax\t\t: 128,\n\t\tdefault\t: 32,\n\t} as const\n\t\n\n\t/**\n\t * Default AES algorithms used based on functionality.\n\t */\n\tstatic readonly DEFAULT_ALGORITHM = {\n\t\tbuffer: 'aes-256-gcm',\n\t\tstream: 'aes-256-cbc',\n\t} as const\n\n\n\t/**\n\t * Supported AES algorithms.\n\t */\n\tstatic readonly ALGORITHMS: Cph.AesAlgorithm[] = [\n\t\t'aes-128-cbc', 'aes-128-ccm', 'aes-128-gcm', 'aes-128-ocb',\n\t\t'aes-192-cbc', 'aes-192-ccm', 'aes-192-gcm', 'aes-192-ocb',\n\t\t'aes-256-cbc', 'aes-256-ccm', 'aes-256-gcm', 'aes-256-ocb',\n\t\t'chacha20-poly1305'\n\t] as const\n\n\n\t/**\n\t * Encrypt in-memory data buffer.\n\t *\n\t * ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.hybridEncrypt()} methods for large data encryption.\n\t *\n\t * @param\tdata\tThe data to encrypt.\n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions\t( Optional ) Additional options.\n\t * @returns\tThe encrypted result Buffer.\n\t */\n\tstatic encrypt(\n\t\tdata\t: CoerceToUint8ArrayInput,\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t): Buffer\n\t{\n\t\tconst _data = coerceToUint8Array( data )\n\n\t\tconst {\n\t\t\tsalt, Key, IV, AAD,\n\t\t\toptions: { algorithm, authTag: authTagLength },\n\t\t} = Cipher.newKeyIV( secret, options )\n\n\t\tif ( Cipher.isCBC( algorithm ) ) {\n\t\t\tconst cipher\t= crypto.createCipheriv( algorithm, Key, IV )\n\t\t\tconst encrypted\t= Buffer.concat( [ cipher.update( _data ), cipher.final() ] )\n\n\t\t\treturn Buffer.concat( [ salt, IV, encrypted ] )\n\t\t}\n\n\n\t\tconst cipher = (\n\t\t\tcrypto.createCipheriv(\n\t\t\t\t// @ts-expect-error `crypto.createCipheriv` cannot infer the correct overload based on the given union type algorithm.\n\t\t\t\talgorithm, Key, IV, { authTagLength }\n\t\t\t)\n\t\t)\n\t\t\n\t\t\n\t\tif ( Cipher.isCCM( algorithm ) ) {\n\t\t\t// AES-CCM requires `plaintextLength`\n\t\t\tcipher.setAAD( AAD, { plaintextLength: _data.length } )\n\t\t}\n\n\t\tif ( Cipher.isGCM( algorithm ) || Cipher.isOCB( algorithm ) ) {\n\t\t\t// AES-GCM and AES-OCB doesn't require `plaintextLength`\n\t\t\tcipher.setAAD( AAD )\n\t\t}\n\n\t\tconst encrypted\t= Buffer.concat( [ cipher.update( _data ), cipher.final() ] )\n\t\tconst authTag\t= cipher.getAuthTag()\n\n\t\treturn Buffer.concat( [ salt, IV, AAD, authTag, encrypted ] )\n\t}\n\n\n\t/**\n\t * Decrypt in-memory data buffer.\n\t *\n\t * ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.hybridDecrypt()} methods for large data decryption.\n\t *\n\t * @param\tdata\tThe data to decrypt.\n\t * @param\tsecret\tThe secret key used to decrypt the `data`.\n\t * @param\toptions\t( Optional ) Additional options. Must be the same used while encrypting data.\n\t * @returns\tThe decrypted data Buffer.\n\t */\n\tstatic decrypt(\n\t\tdata\t: CoerceToUint8ArrayInput,\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t): Buffer\n\t{\n\t\tlet _data\t\t\t= coerceToUint8Array( data )\n\t\tconst _secret\t\t= coerceToUint8Array( secret )\n\t\tconst _options\t\t= Cipher.resolveOptions( options )\n\t\tconst { algorithm }\t= _options\n\n\t\tconst salt\t\t= _data.subarray( 0, _options.salt )\n\t\t_data\t\t\t= _data.subarray( _options.salt )\n\t\tconst IV\t\t= _data.subarray( 0, _options.iv )\n\t\t_data\t\t\t= _data.subarray( _options.iv )\n\t\tconst Key\t\t= crypto.scryptSync( _secret, salt, _options.length )\n\n\t\tif ( Cipher.isCBC( algorithm ) ) {\n\t\t\tconst decipher = (\n\t\t\t\tcrypto.createDecipheriv( _options.algorithm, Key, IV )\n\t\t\t)\n\n\t\t\treturn (\n\t\t\t\tBuffer.concat( [ decipher.update( _data ), decipher.final() ] )\n\t\t\t)\n\t\t}\n\n\t\tconst AADLength\t\t= _options.aadLength\n\t\tconst authTagLength\t= _options.authTag\n\t\tconst AAD\t\t\t= _data.subarray( 0, AADLength )\n\t\t_data\t\t\t\t= _data.subarray( AADLength )\n\t\tconst authTag\t\t= _data.subarray( 0, authTagLength )\n\t\t_data\t\t\t\t= _data.subarray( authTagLength )\n\n\n\t\tconst decipher = (\n\t\t\tcrypto.createDecipheriv(\n\t\t\t\t// @ts-expect-error `crypto.createDecipheriv` cannot infer the correct overload based on the given union type algorithm.\n\t\t\t\talgorithm, Key, IV, { authTagLength }\n\t\t\t)\n\t\t)\n\n\t\tif ( Cipher.isCCM( algorithm ) ) {\n\t\t\t// AES-CCM requires `plaintextLength`\n\t\t\tdecipher.setAAD( AAD, { plaintextLength: _data.length } )\n\t\t}\n\n\t\tif ( Cipher.isGCM( algorithm ) || Cipher.isOCB( algorithm ) ) {\n\t\t\t// AES-GCM and AES-OCB doesn't require `plaintextLength`\n\t\t\tdecipher.setAAD( AAD )\n\t\t}\n\n\t\tdecipher.setAuthTag( authTag )\n\t\n\t\treturn (\n\t\t\tBuffer.concat( [ decipher.update( _data ), decipher.final() ] )\n\t\t)\n\n\t}\n\n\n\t/**\n\t * Encrypt a `Readable` to a `Writable` Stream.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t * \n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions Additional options.\n\t * @returns An object containing:\n\t * \t- a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.\n\t * \t- the actual `encrypt` callback that must be called and awaited in order to start the encryption process.\n\t */\n\tstatic streamEncrypt(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Stream.Symmetric.EncryptOptions,\n\t): Cph.Stream.Symmetric.EncryptReturnType\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tKey, IV, options: { input, output, algorithm, salt, iv, authTag },\n\t\t} = Cipher.newKeyIV<Cph.Stream.Symmetric.EncryptResolvedOptions>( secret, options )\n\n\t\tconst encryptedKey = (\n\t\t\tCipher.encrypt( Buffer.concat( [ Key, IV ] ), secret, { algorithm, salt, iv, authTag } )\n\t\t)\n\n\t\tconst cipher = crypto.createCipheriv( algorithm, Key, IV )\n\t\tconst encrypt = () => (\n\t\t\tCipher.stream( {\n\t\t\t\tcipher, input, output, encryptedKey\n\t\t\t} )\n\t\t)\n\n\t\treturn { cipher, encrypt }\n\t}\n\n\n\t/**\n\t * Decrypt a `Readable` to a `Writable` Stream.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t * \n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions Additional options.\n\t * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:\n\t * \t- a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n\t * \t- the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\t */\n\tstatic streamDecrypt(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Stream.Symmetric.DecryptOptions,\n\t): Promise<Cph.Stream.Symmetric.DecryptReturnType>\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tinput, output, algorithm, salt, iv, authTag, length\n\t\t} = Cipher.resolveOptions<Cph.Stream.Symmetric.DecryptResolvedOptions>( options )\n\n\t\tconst keyIvLength = (\n\t\t\tlength + iv\n\t\t\t+ salt + iv + authTag\n\t\t)\n\n\t\treturn (\n\t\t\tCipher.extractKeyIV( input, keyIvLength )\n\t\t\t\t.then( ( [ encryptedKeyIV, input ] ) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Check if input has error and re-throw if so.\n\t\t\t\t\t * This is required since `.on( 'error' )` listeners attached in\n\t\t\t\t\t * `Cipher.decipherStream()` get attached too late (error event already emitted).\n\t\t\t\t\t */\n\t\t\t\t\tif ( input.errored ) throw input.errored\n\t\t\t\t\t\n\t\t\t\t\tconst KeyIV = (\n\t\t\t\t\t\tCipher.decrypt( encryptedKeyIV, secret, { algorithm, salt, iv, authTag } )\n\t\t\t\t\t)\n\n\t\t\t\t\tconst Key\t\t= KeyIV.subarray( 0, length )\n\t\t\t\t\tconst IV\t\t= KeyIV.subarray( length )\n\t\t\t\t\tconst decipher\t= crypto.createDecipheriv( algorithm, Key, IV )\n\t\n\t\t\t\t\tconst decrypt = () => (\n\t\t\t\t\t\tCipher.decipherStream(\n\t\t\t\t\t\t\t{ decipher, input, output }\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\n\t\t\t\t\treturn { decipher, decrypt }\n\t\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.\n\t *\n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t *\n\t * @param\tsecret\t\tThe secret key used to encrypt the stream.\n\t * @param\tpublicKey\tThe RSA public key used to encrypt the symmetric key.\n\t * @param\toptions\t\tOptions for the stream encryption.\n\t * @returns An object containing:\n\t * \t- a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.\n\t * \t- the actual `encrypt` callback that must be called and awaited in order to start the encryption process.\n\t */\n\tstatic hybridEncrypt(\n\t\tsecret\t\t: CoerceToUint8ArrayInput,\n\t\tpublicKey\t: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike,\n\t\toptions\t\t: Cph.Stream.Hybrid.EncryptOptions,\n\t): Cph.Stream.Hybrid.EncryptReturnType\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tKey, IV,\n\t\t\toptions: { algorithm, input, output },\n\t\t} = Cipher.newKeyIV<Cph.Stream.Hybrid.EncryptResolvedOptions>( secret, options )\n\n\t\tconst encryptedKey = (\n\t\t\tcrypto.publicEncrypt( publicKey, Buffer.concat( [ Key, IV ] ) )\n\t\t)\n\n\t\tconst cipher = crypto.createCipheriv( algorithm, Key, IV )\n\t\tconst encrypt = () => (\n\t\t\tCipher.stream( {\n\t\t\t\tcipher, input, output, encryptedKey\n\t\t\t} )\n\t\t)\n\n\t\treturn { cipher, encrypt }\n\t}\n\n\n\t/**\n\t * Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t *\n\t * @param\tprivateKey\tThe RSA private key used to decrypt the symmetric key.\n\t * @param\toptions\t\tOptions for the stream decryption.\n\t * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:\n\t * \t- a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n\t * \t- the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\t */\n\tstatic hybridDecrypt(\n\t\tprivateKey\t: crypto.RsaPrivateKey | crypto.KeyLike,\n\t\toptions\t\t: Cph.Stream.Hybrid.DecryptOptions,\n\t): Promise<Cph.Stream.Hybrid.DecryptReturnType>\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tinput, output, algorithm, length, rsaKeyLength,\n\t\t} = Cipher.resolveOptions<Cph.Stream.Hybrid.DecryptResolvedOptions>( options )\n\n\t\treturn (\n\t\t\tCipher.extractKeyIV( input, rsaKeyLength )\n\t\t\t\t.then( ( [ encryptedKeyIV, input ] ) => {\n\t\t\t\t\tconst KeyIV\t\t= crypto.privateDecrypt( privateKey, encryptedKeyIV )\n\t\t\t\t\tconst Key\t\t= KeyIV.subarray( 0, length )\n\t\t\t\t\tconst IV\t\t= KeyIV.subarray( length )\n\t\t\t\t\tconst decipher\t= crypto.createDecipheriv( algorithm, Key, IV )\n\t\n\t\t\t\t\tconst decrypt = () => (\n\t\t\t\t\t\tCipher.decipherStream(\n\t\t\t\t\t\t\t{ decipher, input, output }\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\n\t\t\t\t\treturn { decipher, decrypt }\n\t\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Handle pipe flow to encrypt a Stream.\n\t * \n\t * @param\toptions Required parameters.\n\t * @returns A new Promise that resolves `void` once stream is completed.\n\t */\n\tprivate static stream( options: StreamEncryptOptions )\n\t{\n\t\tconst {\n\t\t\tcipher, encryptedKey,\n\t\t\tinput, output\n\t\t} = options\n\n\t\treturn (\n\t\t\tnew Promise<void>( ( resolve, reject ) => {\n\t\t\t\tcipher.on( 'error', reject )\n\t\t\t\tinput.on( 'error', reject )\n\t\t\t\toutput.on( 'error', reject )\n\t\t\t\toutput.on( 'finish', resolve )\n\t\t\n\t\t\t\toutput.write( encryptedKey )\n\t\t\t\tinput.pipe( cipher ).pipe( output )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Handle pipe flow to decrypt a Stream.\n\t * \n\t * @param\toptions Required parameters.\n\t * @returns A new Promise that resolves `void` once stream is completed.\n\t */\n\tprivate static decipherStream( options: StreamDecryptOptions )\n\t{\n\t\tconst {\n\t\t\tdecipher, input, output,\n\t\t} = options\n\n\t\treturn (\n\t\t\tnew Promise<void>( ( resolve, reject ) => {\n\t\t\t\tdecipher.on( 'error', reject )\n\t\t\t\tinput.on( 'error', reject )\n\t\t\t\toutput.on( 'error', reject )\n\t\t\t\toutput.on( 'finish', resolve )\n\n\t\t\t\tinput.pipe( decipher ).pipe( output )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Extract the Cipher Encrypted Symmetric Key and Initialization Vector from an encrypted `Readable` Stream.\n\t *\n\t * @param\tinput\t\tThe `Readable` Stream.\n\t * @param\tkeyLength\tThe encrypted key length in bytes. This is used to properly extract the encrypted Cipher Key and Initialization Vector.\n\t * @returns\tA new Promise that resolve a tuple containing the Cipher Encrypted Symmetric Key and Initialization Vector once fulfilled.\n\t */\n\tprivate static extractKeyIV(\n\t\tinput\t\t: Readable,\n\t\tkeyLength\t: number,\n\t)\n\t{\n\t\treturn (\n\t\t\tnew Promise<[ KeyIV: Buffer, input: Transform ]>( ( resolve, reject ) => {\n\t\t\t\tlet KeyIV\t\t= Buffer.alloc( 0 )\n\t\t\t\tlet bytesRead\t= 0\n\t\t\t\tlet resolved\t= false\n\n\t\t\t\tconst transform = new Transform( {\n\t\t\t\t\tasync transform( chunk: Buffer, encoding, callback )\n\t\t\t\t\t{\n\n\t\t\t\t\t\tif ( KeyIV.length < keyLength ) {\n\t\t\t\t\t\t\tKeyIV = Buffer.concat( [ KeyIV, chunk ] )\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbytesRead += chunk.length\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * `KeyIV` length may exceed the `keyLength`.\n\t\t\t\t\t\t * This may occurs when the received chunk length is not a multiple of the `keyLength`.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * In that case the chunk will contain mixed content:\n\t\t\t\t\t\t * - end of the `KeyIV`.\n\t\t\t\t\t\t * - begin of the actual encrypted data.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * For a proper data handling we need to:\n\t\t\t\t\t\t * - cut off the `KeyIV` to `keyLength` bytes.\n\t\t\t\t\t\t * - recover and push the byte loss to the next piped destination.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif ( KeyIV.length > keyLength ) {\n\t\t\t\t\t\t\tconst bytesLoss\t= Math.max( 0, KeyIV.length - keyLength )\n\t\t\t\t\t\t\tKeyIV\t\t\t= KeyIV.subarray( 0, keyLength )\n\t\t\t\t\t\t\tconst subchunk\t= chunk.subarray( bytesLoss * -1 )\n\n\t\t\t\t\t\t\tif ( ! resolved ) {\n\t\t\t\t\t\t\t\tresolve( [ KeyIV, this ] )\n\t\t\t\t\t\t\t\tresolved = true\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Push to the next piped destination.\n\t\t\t\t\t\t\t */\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.push( subchunk, encoding )\n\n\t\t\t\t\t\t\treturn callback()\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * `KeyIV` has been read.\n\t\t\t\t\t\t * The Received chunk can now be pushed to the next piped destination.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif ( bytesRead > keyLength ) {\n\t\t\t\t\t\t\tif ( ! resolved ) {\n\t\t\t\t\t\t\t\tresolve( [ KeyIV, this ] )\n\t\t\t\t\t\t\t\tresolved = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Push to the next piped destination.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.push( chunk, encoding )\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn callback()\n\t\t\t\t\t},\n\t\t\t\t\tfinal( callback )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( KeyIV.length < keyLength ) {\n\t\t\t\t\t\t\treturn callback(\n\t\t\t\t\t\t\t\tnew Error( 'The extracted KeyIV length is less than the expected length.' )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn callback()\n\t\t\t\t\t},\n\t\t\t\t} )\n\n\t\t\t\ttransform.on( 'error', reject )\n\t\t\t\tinput.on( 'error', error => {\n\t\t\t\t\ttransform.destroy( error )\n\t\t\t\t\treject( error )\n\t\t\t\t} )\n\t\t\t\tinput.pipe( transform )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Generates a `Scrypt` Symmetric Key and the Initialization Vector with the given options.\n\t * \n\t * @param\tsecret\tThe secret key.\n\t * @param\toptions\t( Optional ) Additional options.\n\t * \n\t * @returns An object with the generated `Key`, `IV`, `salt` and resolved `options`. \n\t */\n\tstatic newKeyIV<T extends Cph.ResolvedOptions = Cph.ResolvedOptions>(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t)\n\t{\n\t\tconst _secret\t= coerceToUint8Array( secret )\n\t\tconst _options\t= Cipher.resolveOptions<T>( options )\n\t\tconst salt\t\t= crypto.randomBytes( _options.salt )\n\t\tconst Key\t\t= crypto.scryptSync( _secret, salt, _options.length )\n\t\tconst IV\t\t= crypto.randomBytes( _options.iv )\n\t\tconst AAD\t\t= _options.aad || crypto.scryptSync( Key, salt, _options.aadLength )\n\n\t\treturn { options: _options, Key, IV, AAD, salt }\n\t}\n\n\n\t/**\n\t * Resolves the given `options` with `Cipher` defaults and constraints.\n\t * \n\t * @param options ( Optional ) Additional options.\n\t * @returns The given `options` with `Cipher` defaults and constraints.\n\t */\n\tstatic resolveOptions<\n\t\tT extends Cph.ResolvedOptions = Cph.ResolvedOptions\n\t>( options: Cph.Options = {} ): T\n\t{\n\t\tconst _options = { ...options } as T\n\n\t\tif ( _options.aad ) {\n\t\t\t_options.aad = coerceToUint8Array( _options.aad )\n\t\t}\n\n\t\t_options.salt\t\t||= Cipher.SALT_LENGTH.default\n\t\t_options.authTag\t||= Cipher.AUTH_TAG_LENGTH.default\n\t\t_options.aadLength\t= _options.aad?.length || _options.aadLength || Cipher.AAD_LENGTH.default\n\t\t_options.salt\t\t= Math.min( Math.max( _options.salt, Cipher.SALT_LENGTH.min ), Cipher.SALT_LENGTH.max )\n\t\t_options.authTag\t= Math.min( Math.max( _options.authTag, Cipher.AUTH_TAG_LENGTH.min ), Cipher.AUTH_TAG_LENGTH.max )\n\t\tif ( ! _options.aad ) {\n\t\t\t_options.aadLength\t= Math.min( Math.max( _options.aadLength, Cipher.AAD_LENGTH.min ), Cipher.AAD_LENGTH.max )\n\t\t}\n\n\t\tconst { keyLength, algorithm } = Cipher.getKeyLength( options.algorithm )\n\n\t\t_options.algorithm\t= algorithm\n\t\t_options.length\t\t= keyLength\n\t\t_options.iv\t\t\t= Cipher.getIVLength( algorithm, options )\n\n\t\treturn _options\n\t}\n\n\n\t/**\n\t * Get the Initialization Vector length based on the given algorithm.\n\t * \n\t * @param\talgorithm The algorithm in use.\n\t * @param\toptions ( Optional ) Additional options. \n\t * @returns\tThe Initialization Vector length based on the given algorithm\n\t */\n\tprivate static getIVLength(\n\t\talgorithm\t: Cph.Options[ 'algorithm' ] = Cipher.DEFAULT_ALGORITHM.buffer,\n\t\toptions\t\t: Cph.Options = {},\n\t)\n\t{\n\t\tswitch ( algorithm ) {\n\t\t\tcase 'aes-128-ccm':\n\t\t\tcase 'aes-128-ocb':\n\t\t\tcase 'aes-192-ccm':\n\t\t\tcase 'aes-192-ocb':\n\t\t\tcase 'aes-256-ccm':\n\t\t\tcase 'aes-256-ocb':\n\t\t\t\treturn 8\n\t\t\tcase 'chacha20-poly1305':\n\t\t\t\treturn 12\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\tMath.min(\n\t\t\t\t\t\tMath.max(\n\t\t\t\t\t\t\toptions.iv || Cipher.IV_LENGTH.default,\n\t\t\t\t\t\t\tCipher.IV_LENGTH.min\n\t\t\t\t\t\t), Cipher.IV_LENGTH.max\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t}\n\t}\n\n\n\t/**\n\t * Ensure correct key length based on the given algorithm.\n\t *\n\t * @param\talgorithm The AES algorithm name.\n\t * @returns\tAn object with validated `algorithm` and `keyLength`.\n\t */\n\tprivate static getKeyLength(\n\t\talgorithm: Cph.Options[ 'algorithm' ] = Cipher.DEFAULT_ALGORITHM.buffer\n\t)\n\t{\n\t\tswitch ( algorithm ) {\n\t\t\tcase 'chacha20-poly1305':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 256 / 8,\n\t\t\t\t} as const\n\t\t\tcase 'aes-128-cbc':\n\t\t\tcase 'aes-128-ccm':\n\t\t\tcase 'aes-128-gcm':\n\t\t\tcase 'aes-128-ocb':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 128 / 8, // AES-128 needs a 128 bit (16 bytes)\n\t\t\t\t} as const\n\t\t\tcase 'aes-192-cbc':\n\t\t\tcase 'aes-192-ccm':\n\t\t\tcase 'aes-192-gcm':\n\t\t\tcase 'aes-192-ocb':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 192 / 8, // AES-192 needs a 192 bit (24 bytes)\n\t\t\t\t} as const\n\t\t\tcase 'aes-256-cbc':\n\t\t\tcase 'aes-256-ccm':\n\t\t\tcase 'aes-256-gcm':\n\t\t\tcase 'aes-256-ocb':\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 256 / 8, // AES-256 needs a 256 bit (32 bytes)\n\t\t\t\t} as const\n\t\t}\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-GCM algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-GCM algorithm. `false` otherwise.\n\t */\n\tstatic isGCM( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherGCMTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-gcm' ||\n\t\t\talgorithm === 'aes-192-gcm' ||\n\t\t\talgorithm === 'aes-256-gcm'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-CCM algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-CCM algorithm. `false` otherwise.\n\t */\n\tstatic isCCM( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherCCMTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-ccm' ||\n\t\t\talgorithm === 'aes-192-ccm' ||\n\t\t\talgorithm === 'aes-256-ccm' ||\n\t\t\talgorithm === 'chacha20-poly1305'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-OCB algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-OCB algorithm. `false` otherwise.\n\t */\n\tstatic isOCB( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherOCBTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-ocb' ||\n\t\t\talgorithm === 'aes-192-ocb' ||\n\t\t\talgorithm === 'aes-256-ocb'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-CBC algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-CBC algorithm. `false` otherwise.\n\t */\n\tstatic isCBC( algorithm: Cph.AesAlgorithm ): algorithm is Cph.CBCTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-cbc' ||\n\t\t\talgorithm === 'aes-192-cbc' ||\n\t\t\talgorithm === 'aes-256-cbc'\n\t\t)\n\t}\n}"]}
package/dist/index.mjs CHANGED
@@ -1 +1,2 @@
1
- import u from'crypto';import {Transform}from'stream';import {coerceToUint8Array}from'@alessiofrittoli/crypto-buffer/coercion';var t=class t{static encrypt(a,e,o={}){let r=coerceToUint8Array(a),{salt:n,Key:c,IV:i,AAD:p,options:{algorithm:s,authTag:h}}=t.newKeyIV(e,o);if(t.isCBC(s)){let d=u.createCipheriv(s,c,i),f=Buffer.concat([d.update(r),d.final()]);return Buffer.concat([n,i,f])}let y=u.createCipheriv(s,c,i,{authTagLength:h});t.isCCM(s)&&y.setAAD(p,{plaintextLength:r.length}),(t.isGCM(s)||t.isOCB(s))&&y.setAAD(p);let m=Buffer.concat([y.update(r),y.final()]),l=y.getAuthTag();return Buffer.concat([n,i,p,l,m])}static decrypt(a,e,o={}){let r=coerceToUint8Array(a),n=coerceToUint8Array(e),c=t.resolveOptions(o),{algorithm:i}=c,p=r.subarray(0,c.salt);r=r.subarray(c.salt);let s=r.subarray(0,c.iv);r=r.subarray(c.iv);let h=u.scryptSync(n,p,c.length);if(t.isCBC(i)){let T=u.createDecipheriv(c.algorithm,h,s);return Buffer.concat([T.update(r),T.final()])}let y=c.aadLength,m=c.authTag,l=r.subarray(0,y);r=r.subarray(y);let d=r.subarray(0,m);r=r.subarray(m);let f=u.createDecipheriv(i,h,s,{authTagLength:m});return t.isCCM(i)&&f.setAAD(l,{plaintextLength:r.length}),(t.isGCM(i)||t.isOCB(i))&&f.setAAD(l),f.setAuthTag(d),Buffer.concat([f.update(r),f.final()])}static streamEncrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:o,IV:r,options:{input:n,output:c,algorithm:i,salt:p,iv:s,authTag:h}}=t.newKeyIV(a,e),y=t.encrypt(Buffer.concat([o,r]),a,{algorithm:i,salt:p,iv:s,authTag:h});return t.stream({Key:o,IV:r,input:n,output:c,encryptedKey:y,algorithm:i})}static streamDecrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:r,algorithm:n,salt:c,iv:i,authTag:p,length:s}=t.resolveOptions(e),h=s+i+c+i+p;return t.extractKeyIV(o,h).then(([y,m])=>{if(m.errored)throw m.errored;let l=t.decrypt(y,a,{algorithm:n,salt:c,iv:i,authTag:p});return t.decipherStream({KeyIV:l,length:s,input:m,output:r,algorithm:n})})}static hybridEncrypt(a,e,o){o.algorithm||(o.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:r,IV:n,options:{algorithm:c,input:i,output:p}}=t.newKeyIV(a,o),s=u.publicEncrypt(e,Buffer.concat([r,n]));return t.stream({Key:r,IV:n,input:i,output:p,encryptedKey:s,algorithm:c})}static hybridDecrypt(a,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:r,algorithm:n,length:c,rsaKeyLength:i}=t.resolveOptions(e);return t.extractKeyIV(o,i).then(([p,s])=>{if(s.errored)throw s.errored;let h=u.privateDecrypt(a,p);return t.decipherStream({KeyIV:h,length:c,input:s,output:r,algorithm:n})})}static stream(a){let{Key:e,IV:o,encryptedKey:r,input:n,output:c,algorithm:i}=a;return new Promise((p,s)=>{let h=u.createCipheriv(i,e,o);h.on("error",s),n.on("error",s),c.on("error",s),c.on("finish",p),c.write(r),n.pipe(h).pipe(c);})}static decipherStream(a){let{KeyIV:e,length:o,algorithm:r,input:n,output:c}=a;return new Promise((i,p)=>{let s=e.subarray(0,o),h=e.subarray(o),y=u.createDecipheriv(r,s,h);y.on("error",p),n.on("error",p),c.on("error",p),c.on("finish",i),n.pipe(y).pipe(c);})}static extractKeyIV(a,e){return new Promise((o,r)=>{let n=Buffer.alloc(0),c=0,i=false,p=new Transform({async transform(s,h,y){if(n.length<e&&(n=Buffer.concat([n,s])),c+=s.length,n.length>e){let m=Math.max(0,n.length-e);n=n.subarray(0,e);let l=s.subarray(m*-1);return i||(o([n,this]),i=true),this.push(l,h),y()}return c>e&&(i||(o([n,this]),i=true),this.push(s,h)),y()},final(s){return n.length<e?s(new Error("The extracted KeyIV length is less than the expected length.")):s()}});p.on("error",r),a.on("error",s=>{p.destroy(s),r(s);}),a.pipe(p);})}static newKeyIV(a,e={}){let o=coerceToUint8Array(a),r=t.resolveOptions(e),n=u.randomBytes(r.salt),c=u.scryptSync(o,n,r.length),i=u.randomBytes(r.iv),p=r.aad||u.scryptSync(c,n,r.aadLength);return {options:r,Key:c,IV:i,AAD:p,salt:n}}static resolveOptions(a={}){let e={...a};e.aad&&(e.aad=coerceToUint8Array(e.aad)),e.salt||(e.salt=t.SALT_LENGTH.default),e.authTag||(e.authTag=t.AUTH_TAG_LENGTH.default),e.aadLength=e.aad?.length||e.aadLength||t.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,t.SALT_LENGTH.min),t.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,t.AUTH_TAG_LENGTH.min),t.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,t.AAD_LENGTH.min),t.AAD_LENGTH.max));let{keyLength:o,algorithm:r}=t.getKeyLength(a.algorithm);return e.algorithm=r,e.length=o,e.iv=t.getIVLength(r,a),e}static getIVLength(a=t.DEFAULT_ALGORITHM.buffer,e={}){switch(a){case "aes-128-ccm":case "aes-128-ocb":case "aes-192-ccm":case "aes-192-ocb":case "aes-256-ccm":case "aes-256-ocb":return 8;case "chacha20-poly1305":return 12;default:return Math.min(Math.max(e.iv||t.IV_LENGTH.default,t.IV_LENGTH.min),t.IV_LENGTH.max)}}static getKeyLength(a=t.DEFAULT_ALGORITHM.buffer){switch(a){case "chacha20-poly1305":return {algorithm:a,keyLength:256/8};case "aes-128-cbc":case "aes-128-ccm":case "aes-128-gcm":case "aes-128-ocb":return {algorithm:a,keyLength:128/8};case "aes-192-cbc":case "aes-192-ccm":case "aes-192-gcm":case "aes-192-ocb":return {algorithm:a,keyLength:192/8};case "aes-256-cbc":case "aes-256-ccm":case "aes-256-gcm":case "aes-256-ocb":default:return {algorithm:a,keyLength:256/8}}}static isGCM(a){return a==="aes-128-gcm"||a==="aes-192-gcm"||a==="aes-256-gcm"}static isCCM(a){return a==="aes-128-ccm"||a==="aes-192-ccm"||a==="aes-256-ccm"||a==="chacha20-poly1305"}static isOCB(a){return a==="aes-128-ocb"||a==="aes-192-ocb"||a==="aes-256-ocb"}static isCBC(a){return a==="aes-128-cbc"||a==="aes-192-cbc"||a==="aes-256-cbc"}};t.SALT_LENGTH={min:16,max:64,default:32},t.IV_LENGTH={min:8,max:32,default:16},t.AUTH_TAG_LENGTH={min:4,max:16,default:16},t.AAD_LENGTH={min:16,max:128,default:32},t.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},t.ALGORITHMS=["aes-128-cbc","aes-128-ccm","aes-128-gcm","aes-128-ocb","aes-192-cbc","aes-192-ccm","aes-192-gcm","aes-192-ocb","aes-256-cbc","aes-256-ccm","aes-256-gcm","aes-256-ocb","chacha20-poly1305"];var A=t;export{A as Cipher};
1
+ import m from'crypto';import {Transform}from'stream';import {coerceToUint8Array}from'@alessiofrittoli/crypto-buffer/coercion';var t=class t{static encrypt(r,e,o={}){let a=coerceToUint8Array(r),{salt:c,Key:s,IV:n,AAD:p,options:{algorithm:i,authTag:h}}=t.newKeyIV(e,o);if(t.isCBC(i)){let T=m.createCipheriv(i,s,n),d=Buffer.concat([T.update(a),T.final()]);return Buffer.concat([c,n,d])}let y=m.createCipheriv(i,s,n,{authTagLength:h});t.isCCM(i)&&y.setAAD(p,{plaintextLength:a.length}),(t.isGCM(i)||t.isOCB(i))&&y.setAAD(p);let u=Buffer.concat([y.update(a),y.final()]),l=y.getAuthTag();return Buffer.concat([c,n,p,l,u])}static decrypt(r,e,o={}){let a=coerceToUint8Array(r),c=coerceToUint8Array(e),s=t.resolveOptions(o),{algorithm:n}=s,p=a.subarray(0,s.salt);a=a.subarray(s.salt);let i=a.subarray(0,s.iv);a=a.subarray(s.iv);let h=m.scryptSync(c,p,s.length);if(t.isCBC(n)){let f=m.createDecipheriv(s.algorithm,h,i);return Buffer.concat([f.update(a),f.final()])}let y=s.aadLength,u=s.authTag,l=a.subarray(0,y);a=a.subarray(y);let T=a.subarray(0,u);a=a.subarray(u);let d=m.createDecipheriv(n,h,i,{authTagLength:u});return t.isCCM(n)&&d.setAAD(l,{plaintextLength:a.length}),(t.isGCM(n)||t.isOCB(n))&&d.setAAD(l),d.setAuthTag(T),Buffer.concat([d.update(a),d.final()])}static streamEncrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:o,IV:a,options:{input:c,output:s,algorithm:n,salt:p,iv:i,authTag:h}}=t.newKeyIV(r,e),y=t.encrypt(Buffer.concat([o,a]),r,{algorithm:n,salt:p,iv:i,authTag:h}),u=m.createCipheriv(n,o,a);return {cipher:u,encrypt:()=>t.stream({cipher:u,input:c,output:s,encryptedKey:y})}}static streamDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,salt:s,iv:n,authTag:p,length:i}=t.resolveOptions(e),h=i+n+s+n+p;return t.extractKeyIV(o,h).then(([y,u])=>{if(u.errored)throw u.errored;let l=t.decrypt(y,r,{algorithm:c,salt:s,iv:n,authTag:p}),T=l.subarray(0,i),d=l.subarray(i),f=m.createDecipheriv(c,T,d);return {decipher:f,decrypt:()=>t.decipherStream({decipher:f,input:u,output:a})}})}static hybridEncrypt(r,e,o){o.algorithm||(o.algorithm=t.DEFAULT_ALGORITHM.stream);let{Key:a,IV:c,options:{algorithm:s,input:n,output:p}}=t.newKeyIV(r,o),i=m.publicEncrypt(e,Buffer.concat([a,c])),h=m.createCipheriv(s,a,c);return {cipher:h,encrypt:()=>t.stream({cipher:h,input:n,output:p,encryptedKey:i})}}static hybridDecrypt(r,e){e.algorithm||(e.algorithm=t.DEFAULT_ALGORITHM.stream);let{input:o,output:a,algorithm:c,length:s,rsaKeyLength:n}=t.resolveOptions(e);return t.extractKeyIV(o,n).then(([p,i])=>{let h=m.privateDecrypt(r,p),y=h.subarray(0,s),u=h.subarray(s),l=m.createDecipheriv(c,y,u);return {decipher:l,decrypt:()=>t.decipherStream({decipher:l,input:i,output:a})}})}static stream(r){let{cipher:e,encryptedKey:o,input:a,output:c}=r;return new Promise((s,n)=>{e.on("error",n),a.on("error",n),c.on("error",n),c.on("finish",s),c.write(o),a.pipe(e).pipe(c);})}static decipherStream(r){let{decipher:e,input:o,output:a}=r;return new Promise((c,s)=>{e.on("error",s),o.on("error",s),a.on("error",s),a.on("finish",c),o.pipe(e).pipe(a);})}static extractKeyIV(r,e){return new Promise((o,a)=>{let c=Buffer.alloc(0),s=0,n=false,p=new Transform({async transform(i,h,y){if(c.length<e&&(c=Buffer.concat([c,i])),s+=i.length,c.length>e){let u=Math.max(0,c.length-e);c=c.subarray(0,e);let l=i.subarray(u*-1);return n||(o([c,this]),n=true),this.push(l,h),y()}return s>e&&(n||(o([c,this]),n=true),this.push(i,h)),y()},final(i){return c.length<e?i(new Error("The extracted KeyIV length is less than the expected length.")):i()}});p.on("error",a),r.on("error",i=>{p.destroy(i),a(i);}),r.pipe(p);})}static newKeyIV(r,e={}){let o=coerceToUint8Array(r),a=t.resolveOptions(e),c=m.randomBytes(a.salt),s=m.scryptSync(o,c,a.length),n=m.randomBytes(a.iv),p=a.aad||m.scryptSync(s,c,a.aadLength);return {options:a,Key:s,IV:n,AAD:p,salt:c}}static resolveOptions(r={}){let e={...r};e.aad&&(e.aad=coerceToUint8Array(e.aad)),e.salt||(e.salt=t.SALT_LENGTH.default),e.authTag||(e.authTag=t.AUTH_TAG_LENGTH.default),e.aadLength=e.aad?.length||e.aadLength||t.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,t.SALT_LENGTH.min),t.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,t.AUTH_TAG_LENGTH.min),t.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,t.AAD_LENGTH.min),t.AAD_LENGTH.max));let{keyLength:o,algorithm:a}=t.getKeyLength(r.algorithm);return e.algorithm=a,e.length=o,e.iv=t.getIVLength(a,r),e}static getIVLength(r=t.DEFAULT_ALGORITHM.buffer,e={}){switch(r){case "aes-128-ccm":case "aes-128-ocb":case "aes-192-ccm":case "aes-192-ocb":case "aes-256-ccm":case "aes-256-ocb":return 8;case "chacha20-poly1305":return 12;default:return Math.min(Math.max(e.iv||t.IV_LENGTH.default,t.IV_LENGTH.min),t.IV_LENGTH.max)}}static getKeyLength(r=t.DEFAULT_ALGORITHM.buffer){switch(r){case "chacha20-poly1305":return {algorithm:r,keyLength:256/8};case "aes-128-cbc":case "aes-128-ccm":case "aes-128-gcm":case "aes-128-ocb":return {algorithm:r,keyLength:128/8};case "aes-192-cbc":case "aes-192-ccm":case "aes-192-gcm":case "aes-192-ocb":return {algorithm:r,keyLength:192/8};case "aes-256-cbc":case "aes-256-ccm":case "aes-256-gcm":case "aes-256-ocb":default:return {algorithm:r,keyLength:256/8}}}static isGCM(r){return r==="aes-128-gcm"||r==="aes-192-gcm"||r==="aes-256-gcm"}static isCCM(r){return r==="aes-128-ccm"||r==="aes-192-ccm"||r==="aes-256-ccm"||r==="chacha20-poly1305"}static isOCB(r){return r==="aes-128-ocb"||r==="aes-192-ocb"||r==="aes-256-ocb"}static isCBC(r){return r==="aes-128-cbc"||r==="aes-192-cbc"||r==="aes-256-cbc"}};t.SALT_LENGTH={min:16,max:64,default:32},t.IV_LENGTH={min:8,max:32,default:16},t.AUTH_TAG_LENGTH={min:4,max:16,default:16},t.AAD_LENGTH={min:16,max:128,default:32},t.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},t.ALGORITHMS=["aes-128-cbc","aes-128-ccm","aes-128-gcm","aes-128-ocb","aes-192-cbc","aes-192-ccm","aes-192-gcm","aes-192-ocb","aes-256-cbc","aes-256-ccm","aes-256-gcm","aes-256-ocb","chacha20-poly1305"];var A=t;export{A as Cipher};//# sourceMappingURL=index.mjs.map
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["_Cipher","data","secret","options","_data","coerceToUint8Array","salt","Key","IV","AAD","algorithm","authTagLength","cipher","crypto","encrypted","authTag","_secret","_options","decipher","AADLength","input","output","iv","encryptedKey","length","keyIvLength","encryptedKeyIV","KeyIV","publicKey","privateKey","rsaKeyLength","resolve","reject","keyLength","bytesRead","resolved","transform","Transform","chunk","encoding","callback","bytesLoss","subchunk","error","Cipher"],"mappings":"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","file":"index.mjs","sourcesContent":["import crypto from 'crypto'\nimport { Transform } from 'stream'\nimport type { Readable, Writable } from 'stream'\nimport { coerceToUint8Array, type CoerceToUint8ArrayInput } from '@alessiofrittoli/crypto-buffer/coercion'\n\nimport type { Cph } from './types'\n\n\n\n/**\n * INTERNAL USE ONLY\n */\ninterface StreamEncryptOptions\n{\n\tcipher\t\t: crypto.Cipher\n\tencryptedKey: Buffer\n\tinput\t\t: Readable\n\toutput\t\t: Writable\n}\n\n\n/**\n * INTERNAL USE ONLY\n */\ninterface StreamDecryptOptions\n{\n\tdecipher\t: crypto.Decipher\n\tinput\t\t: Readable\n\toutput\t\t: Writable\n}\n\n\n/**\n * Utility class for AES encryption and decryption following [NIST SP 800-38D](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf) standard reccomendations.\n */\nexport class Cipher\n{\n\t/**\n\t * Cipher default `salt` lengths.\n\t */\n\tstatic readonly SALT_LENGTH = {\n\t\tmin\t\t: 16,\n\t\tmax\t\t: 64,\n\t\tdefault\t: 32,\n\t} as const\n\n\n\t/**\n\t * Cipher default `IV` lengths.\n\t */\n\tstatic readonly IV_LENGTH = {\n\t\tmin\t\t: 8,\n\t\tmax\t\t: 32,\n\t\tdefault\t: 16,\n\t} as const\n\n\n\t/**\n\t * Cipher default `Auth Tag` lengths.\n\t */\n\tstatic readonly AUTH_TAG_LENGTH = {\n\t\tmin\t\t: 4,\n\t\tmax\t\t: 16,\n\t\tdefault\t: 16,\n\t} as const\n\t\n\t\n\t/**\n\t * Cipher default `Additional Authenticated Data` lengths.\n\t */\n\tstatic readonly AAD_LENGTH = {\n\t\tmin\t\t: 16,\n\t\tmax\t\t: 128,\n\t\tdefault\t: 32,\n\t} as const\n\t\n\n\t/**\n\t * Default AES algorithms used based on functionality.\n\t */\n\tstatic readonly DEFAULT_ALGORITHM = {\n\t\tbuffer: 'aes-256-gcm',\n\t\tstream: 'aes-256-cbc',\n\t} as const\n\n\n\t/**\n\t * Supported AES algorithms.\n\t */\n\tstatic readonly ALGORITHMS: Cph.AesAlgorithm[] = [\n\t\t'aes-128-cbc', 'aes-128-ccm', 'aes-128-gcm', 'aes-128-ocb',\n\t\t'aes-192-cbc', 'aes-192-ccm', 'aes-192-gcm', 'aes-192-ocb',\n\t\t'aes-256-cbc', 'aes-256-ccm', 'aes-256-gcm', 'aes-256-ocb',\n\t\t'chacha20-poly1305'\n\t] as const\n\n\n\t/**\n\t * Encrypt in-memory data buffer.\n\t *\n\t * ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.hybridEncrypt()} methods for large data encryption.\n\t *\n\t * @param\tdata\tThe data to encrypt.\n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions\t( Optional ) Additional options.\n\t * @returns\tThe encrypted result Buffer.\n\t */\n\tstatic encrypt(\n\t\tdata\t: CoerceToUint8ArrayInput,\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t): Buffer\n\t{\n\t\tconst _data = coerceToUint8Array( data )\n\n\t\tconst {\n\t\t\tsalt, Key, IV, AAD,\n\t\t\toptions: { algorithm, authTag: authTagLength },\n\t\t} = Cipher.newKeyIV( secret, options )\n\n\t\tif ( Cipher.isCBC( algorithm ) ) {\n\t\t\tconst cipher\t= crypto.createCipheriv( algorithm, Key, IV )\n\t\t\tconst encrypted\t= Buffer.concat( [ cipher.update( _data ), cipher.final() ] )\n\n\t\t\treturn Buffer.concat( [ salt, IV, encrypted ] )\n\t\t}\n\n\n\t\tconst cipher = (\n\t\t\tcrypto.createCipheriv(\n\t\t\t\t// @ts-expect-error `crypto.createCipheriv` cannot infer the correct overload based on the given union type algorithm.\n\t\t\t\talgorithm, Key, IV, { authTagLength }\n\t\t\t)\n\t\t)\n\t\t\n\t\t\n\t\tif ( Cipher.isCCM( algorithm ) ) {\n\t\t\t// AES-CCM requires `plaintextLength`\n\t\t\tcipher.setAAD( AAD, { plaintextLength: _data.length } )\n\t\t}\n\n\t\tif ( Cipher.isGCM( algorithm ) || Cipher.isOCB( algorithm ) ) {\n\t\t\t// AES-GCM and AES-OCB doesn't require `plaintextLength`\n\t\t\tcipher.setAAD( AAD )\n\t\t}\n\n\t\tconst encrypted\t= Buffer.concat( [ cipher.update( _data ), cipher.final() ] )\n\t\tconst authTag\t= cipher.getAuthTag()\n\n\t\treturn Buffer.concat( [ salt, IV, AAD, authTag, encrypted ] )\n\t}\n\n\n\t/**\n\t * Decrypt in-memory data buffer.\n\t *\n\t * ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.hybridDecrypt()} methods for large data decryption.\n\t *\n\t * @param\tdata\tThe data to decrypt.\n\t * @param\tsecret\tThe secret key used to decrypt the `data`.\n\t * @param\toptions\t( Optional ) Additional options. Must be the same used while encrypting data.\n\t * @returns\tThe decrypted data Buffer.\n\t */\n\tstatic decrypt(\n\t\tdata\t: CoerceToUint8ArrayInput,\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t): Buffer\n\t{\n\t\tlet _data\t\t\t= coerceToUint8Array( data )\n\t\tconst _secret\t\t= coerceToUint8Array( secret )\n\t\tconst _options\t\t= Cipher.resolveOptions( options )\n\t\tconst { algorithm }\t= _options\n\n\t\tconst salt\t\t= _data.subarray( 0, _options.salt )\n\t\t_data\t\t\t= _data.subarray( _options.salt )\n\t\tconst IV\t\t= _data.subarray( 0, _options.iv )\n\t\t_data\t\t\t= _data.subarray( _options.iv )\n\t\tconst Key\t\t= crypto.scryptSync( _secret, salt, _options.length )\n\n\t\tif ( Cipher.isCBC( algorithm ) ) {\n\t\t\tconst decipher = (\n\t\t\t\tcrypto.createDecipheriv( _options.algorithm, Key, IV )\n\t\t\t)\n\n\t\t\treturn (\n\t\t\t\tBuffer.concat( [ decipher.update( _data ), decipher.final() ] )\n\t\t\t)\n\t\t}\n\n\t\tconst AADLength\t\t= _options.aadLength\n\t\tconst authTagLength\t= _options.authTag\n\t\tconst AAD\t\t\t= _data.subarray( 0, AADLength )\n\t\t_data\t\t\t\t= _data.subarray( AADLength )\n\t\tconst authTag\t\t= _data.subarray( 0, authTagLength )\n\t\t_data\t\t\t\t= _data.subarray( authTagLength )\n\n\n\t\tconst decipher = (\n\t\t\tcrypto.createDecipheriv(\n\t\t\t\t// @ts-expect-error `crypto.createDecipheriv` cannot infer the correct overload based on the given union type algorithm.\n\t\t\t\talgorithm, Key, IV, { authTagLength }\n\t\t\t)\n\t\t)\n\n\t\tif ( Cipher.isCCM( algorithm ) ) {\n\t\t\t// AES-CCM requires `plaintextLength`\n\t\t\tdecipher.setAAD( AAD, { plaintextLength: _data.length } )\n\t\t}\n\n\t\tif ( Cipher.isGCM( algorithm ) || Cipher.isOCB( algorithm ) ) {\n\t\t\t// AES-GCM and AES-OCB doesn't require `plaintextLength`\n\t\t\tdecipher.setAAD( AAD )\n\t\t}\n\n\t\tdecipher.setAuthTag( authTag )\n\t\n\t\treturn (\n\t\t\tBuffer.concat( [ decipher.update( _data ), decipher.final() ] )\n\t\t)\n\n\t}\n\n\n\t/**\n\t * Encrypt a `Readable` to a `Writable` Stream.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t * \n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions Additional options.\n\t * @returns An object containing:\n\t * \t- a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.\n\t * \t- the actual `encrypt` callback that must be called and awaited in order to start the encryption process.\n\t */\n\tstatic streamEncrypt(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Stream.Symmetric.EncryptOptions,\n\t): Cph.Stream.Symmetric.EncryptReturnType\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tKey, IV, options: { input, output, algorithm, salt, iv, authTag },\n\t\t} = Cipher.newKeyIV<Cph.Stream.Symmetric.EncryptResolvedOptions>( secret, options )\n\n\t\tconst encryptedKey = (\n\t\t\tCipher.encrypt( Buffer.concat( [ Key, IV ] ), secret, { algorithm, salt, iv, authTag } )\n\t\t)\n\n\t\tconst cipher = crypto.createCipheriv( algorithm, Key, IV )\n\t\tconst encrypt = () => (\n\t\t\tCipher.stream( {\n\t\t\t\tcipher, input, output, encryptedKey\n\t\t\t} )\n\t\t)\n\n\t\treturn { cipher, encrypt }\n\t}\n\n\n\t/**\n\t * Decrypt a `Readable` to a `Writable` Stream.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t * \n\t * @param\tsecret\tThe secret key used to encrypt the `data`.\n\t * @param\toptions Additional options.\n\t * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:\n\t * \t- a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n\t * \t- the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\t */\n\tstatic streamDecrypt(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Stream.Symmetric.DecryptOptions,\n\t): Promise<Cph.Stream.Symmetric.DecryptReturnType>\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tinput, output, algorithm, salt, iv, authTag, length\n\t\t} = Cipher.resolveOptions<Cph.Stream.Symmetric.DecryptResolvedOptions>( options )\n\n\t\tconst keyIvLength = (\n\t\t\tlength + iv\n\t\t\t+ salt + iv + authTag\n\t\t)\n\n\t\treturn (\n\t\t\tCipher.extractKeyIV( input, keyIvLength )\n\t\t\t\t.then( ( [ encryptedKeyIV, input ] ) => {\n\t\t\t\t\t/**\n\t\t\t\t\t * Check if input has error and re-throw if so.\n\t\t\t\t\t * This is required since `.on( 'error' )` listeners attached in\n\t\t\t\t\t * `Cipher.decipherStream()` get attached too late (error event already emitted).\n\t\t\t\t\t */\n\t\t\t\t\tif ( input.errored ) throw input.errored\n\t\t\t\t\t\n\t\t\t\t\tconst KeyIV = (\n\t\t\t\t\t\tCipher.decrypt( encryptedKeyIV, secret, { algorithm, salt, iv, authTag } )\n\t\t\t\t\t)\n\n\t\t\t\t\tconst Key\t\t= KeyIV.subarray( 0, length )\n\t\t\t\t\tconst IV\t\t= KeyIV.subarray( length )\n\t\t\t\t\tconst decipher\t= crypto.createDecipheriv( algorithm, Key, IV )\n\t\n\t\t\t\t\tconst decrypt = () => (\n\t\t\t\t\t\tCipher.decipherStream(\n\t\t\t\t\t\t\t{ decipher, input, output }\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\n\t\t\t\t\treturn { decipher, decrypt }\n\t\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.\n\t *\n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t *\n\t * @param\tsecret\t\tThe secret key used to encrypt the stream.\n\t * @param\tpublicKey\tThe RSA public key used to encrypt the symmetric key.\n\t * @param\toptions\t\tOptions for the stream encryption.\n\t * @returns An object containing:\n\t * \t- a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.\n\t * \t- the actual `encrypt` callback that must be called and awaited in order to start the encryption process.\n\t */\n\tstatic hybridEncrypt(\n\t\tsecret\t\t: CoerceToUint8ArrayInput,\n\t\tpublicKey\t: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike,\n\t\toptions\t\t: Cph.Stream.Hybrid.EncryptOptions,\n\t): Cph.Stream.Hybrid.EncryptReturnType\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tKey, IV,\n\t\t\toptions: { algorithm, input, output },\n\t\t} = Cipher.newKeyIV<Cph.Stream.Hybrid.EncryptResolvedOptions>( secret, options )\n\n\t\tconst encryptedKey = (\n\t\t\tcrypto.publicEncrypt( publicKey, Buffer.concat( [ Key, IV ] ) )\n\t\t)\n\n\t\tconst cipher = crypto.createCipheriv( algorithm, Key, IV )\n\t\tconst encrypt = () => (\n\t\t\tCipher.stream( {\n\t\t\t\tcipher, input, output, encryptedKey\n\t\t\t} )\n\t\t)\n\n\t\treturn { cipher, encrypt }\n\t}\n\n\n\t/**\n\t * Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.\n\t * \n\t * The `Readable` Stream could be 'in-memory buffer' or 'file' based.\n\t *\n\t * @param\tprivateKey\tThe RSA private key used to decrypt the symmetric key.\n\t * @param\toptions\t\tOptions for the stream decryption.\n\t * @returns A new Promise that resolves when Key IV extraction completes returning an object containing:\n\t * \t- a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n\t * \t- the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\t */\n\tstatic hybridDecrypt(\n\t\tprivateKey\t: crypto.RsaPrivateKey | crypto.KeyLike,\n\t\toptions\t\t: Cph.Stream.Hybrid.DecryptOptions,\n\t): Promise<Cph.Stream.Hybrid.DecryptReturnType>\n\t{\n\t\toptions.algorithm ||= Cipher.DEFAULT_ALGORITHM.stream\n\n\t\tconst {\n\t\t\tinput, output, algorithm, length, rsaKeyLength,\n\t\t} = Cipher.resolveOptions<Cph.Stream.Hybrid.DecryptResolvedOptions>( options )\n\n\t\treturn (\n\t\t\tCipher.extractKeyIV( input, rsaKeyLength )\n\t\t\t\t.then( ( [ encryptedKeyIV, input ] ) => {\n\t\t\t\t\tconst KeyIV\t\t= crypto.privateDecrypt( privateKey, encryptedKeyIV )\n\t\t\t\t\tconst Key\t\t= KeyIV.subarray( 0, length )\n\t\t\t\t\tconst IV\t\t= KeyIV.subarray( length )\n\t\t\t\t\tconst decipher\t= crypto.createDecipheriv( algorithm, Key, IV )\n\t\n\t\t\t\t\tconst decrypt = () => (\n\t\t\t\t\t\tCipher.decipherStream(\n\t\t\t\t\t\t\t{ decipher, input, output }\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\n\t\t\t\t\treturn { decipher, decrypt }\n\t\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Handle pipe flow to encrypt a Stream.\n\t * \n\t * @param\toptions Required parameters.\n\t * @returns A new Promise that resolves `void` once stream is completed.\n\t */\n\tprivate static stream( options: StreamEncryptOptions )\n\t{\n\t\tconst {\n\t\t\tcipher, encryptedKey,\n\t\t\tinput, output\n\t\t} = options\n\n\t\treturn (\n\t\t\tnew Promise<void>( ( resolve, reject ) => {\n\t\t\t\tcipher.on( 'error', reject )\n\t\t\t\tinput.on( 'error', reject )\n\t\t\t\toutput.on( 'error', reject )\n\t\t\t\toutput.on( 'finish', resolve )\n\t\t\n\t\t\t\toutput.write( encryptedKey )\n\t\t\t\tinput.pipe( cipher ).pipe( output )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Handle pipe flow to decrypt a Stream.\n\t * \n\t * @param\toptions Required parameters.\n\t * @returns A new Promise that resolves `void` once stream is completed.\n\t */\n\tprivate static decipherStream( options: StreamDecryptOptions )\n\t{\n\t\tconst {\n\t\t\tdecipher, input, output,\n\t\t} = options\n\n\t\treturn (\n\t\t\tnew Promise<void>( ( resolve, reject ) => {\n\t\t\t\tdecipher.on( 'error', reject )\n\t\t\t\tinput.on( 'error', reject )\n\t\t\t\toutput.on( 'error', reject )\n\t\t\t\toutput.on( 'finish', resolve )\n\n\t\t\t\tinput.pipe( decipher ).pipe( output )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Extract the Cipher Encrypted Symmetric Key and Initialization Vector from an encrypted `Readable` Stream.\n\t *\n\t * @param\tinput\t\tThe `Readable` Stream.\n\t * @param\tkeyLength\tThe encrypted key length in bytes. This is used to properly extract the encrypted Cipher Key and Initialization Vector.\n\t * @returns\tA new Promise that resolve a tuple containing the Cipher Encrypted Symmetric Key and Initialization Vector once fulfilled.\n\t */\n\tprivate static extractKeyIV(\n\t\tinput\t\t: Readable,\n\t\tkeyLength\t: number,\n\t)\n\t{\n\t\treturn (\n\t\t\tnew Promise<[ KeyIV: Buffer, input: Transform ]>( ( resolve, reject ) => {\n\t\t\t\tlet KeyIV\t\t= Buffer.alloc( 0 )\n\t\t\t\tlet bytesRead\t= 0\n\t\t\t\tlet resolved\t= false\n\n\t\t\t\tconst transform = new Transform( {\n\t\t\t\t\tasync transform( chunk: Buffer, encoding, callback )\n\t\t\t\t\t{\n\n\t\t\t\t\t\tif ( KeyIV.length < keyLength ) {\n\t\t\t\t\t\t\tKeyIV = Buffer.concat( [ KeyIV, chunk ] )\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbytesRead += chunk.length\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * `KeyIV` length may exceed the `keyLength`.\n\t\t\t\t\t\t * This may occurs when the received chunk length is not a multiple of the `keyLength`.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * In that case the chunk will contain mixed content:\n\t\t\t\t\t\t * - end of the `KeyIV`.\n\t\t\t\t\t\t * - begin of the actual encrypted data.\n\t\t\t\t\t\t *\n\t\t\t\t\t\t * For a proper data handling we need to:\n\t\t\t\t\t\t * - cut off the `KeyIV` to `keyLength` bytes.\n\t\t\t\t\t\t * - recover and push the byte loss to the next piped destination.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif ( KeyIV.length > keyLength ) {\n\t\t\t\t\t\t\tconst bytesLoss\t= Math.max( 0, KeyIV.length - keyLength )\n\t\t\t\t\t\t\tKeyIV\t\t\t= KeyIV.subarray( 0, keyLength )\n\t\t\t\t\t\t\tconst subchunk\t= chunk.subarray( bytesLoss * -1 )\n\n\t\t\t\t\t\t\tif ( ! resolved ) {\n\t\t\t\t\t\t\t\tresolve( [ KeyIV, this ] )\n\t\t\t\t\t\t\t\tresolved = true\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Push to the next piped destination.\n\t\t\t\t\t\t\t */\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tthis.push( subchunk, encoding )\n\n\t\t\t\t\t\t\treturn callback()\n\t\t\t\t\t\t}\n\n\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * `KeyIV` has been read.\n\t\t\t\t\t\t * The Received chunk can now be pushed to the next piped destination.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif ( bytesRead > keyLength ) {\n\t\t\t\t\t\t\tif ( ! resolved ) {\n\t\t\t\t\t\t\t\tresolve( [ KeyIV, this ] )\n\t\t\t\t\t\t\t\tresolved = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * Push to the next piped destination.\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\tthis.push( chunk, encoding )\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn callback()\n\t\t\t\t\t},\n\t\t\t\t\tfinal( callback )\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( KeyIV.length < keyLength ) {\n\t\t\t\t\t\t\treturn callback(\n\t\t\t\t\t\t\t\tnew Error( 'The extracted KeyIV length is less than the expected length.' )\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn callback()\n\t\t\t\t\t},\n\t\t\t\t} )\n\n\t\t\t\ttransform.on( 'error', reject )\n\t\t\t\tinput.on( 'error', error => {\n\t\t\t\t\ttransform.destroy( error )\n\t\t\t\t\treject( error )\n\t\t\t\t} )\n\t\t\t\tinput.pipe( transform )\n\t\t\t} )\n\t\t)\n\t}\n\n\n\t/**\n\t * Generates a `Scrypt` Symmetric Key and the Initialization Vector with the given options.\n\t * \n\t * @param\tsecret\tThe secret key.\n\t * @param\toptions\t( Optional ) Additional options.\n\t * \n\t * @returns An object with the generated `Key`, `IV`, `salt` and resolved `options`. \n\t */\n\tstatic newKeyIV<T extends Cph.ResolvedOptions = Cph.ResolvedOptions>(\n\t\tsecret\t: CoerceToUint8ArrayInput,\n\t\toptions\t: Cph.Options = {},\n\t)\n\t{\n\t\tconst _secret\t= coerceToUint8Array( secret )\n\t\tconst _options\t= Cipher.resolveOptions<T>( options )\n\t\tconst salt\t\t= crypto.randomBytes( _options.salt )\n\t\tconst Key\t\t= crypto.scryptSync( _secret, salt, _options.length )\n\t\tconst IV\t\t= crypto.randomBytes( _options.iv )\n\t\tconst AAD\t\t= _options.aad || crypto.scryptSync( Key, salt, _options.aadLength )\n\n\t\treturn { options: _options, Key, IV, AAD, salt }\n\t}\n\n\n\t/**\n\t * Resolves the given `options` with `Cipher` defaults and constraints.\n\t * \n\t * @param options ( Optional ) Additional options.\n\t * @returns The given `options` with `Cipher` defaults and constraints.\n\t */\n\tstatic resolveOptions<\n\t\tT extends Cph.ResolvedOptions = Cph.ResolvedOptions\n\t>( options: Cph.Options = {} ): T\n\t{\n\t\tconst _options = { ...options } as T\n\n\t\tif ( _options.aad ) {\n\t\t\t_options.aad = coerceToUint8Array( _options.aad )\n\t\t}\n\n\t\t_options.salt\t\t||= Cipher.SALT_LENGTH.default\n\t\t_options.authTag\t||= Cipher.AUTH_TAG_LENGTH.default\n\t\t_options.aadLength\t= _options.aad?.length || _options.aadLength || Cipher.AAD_LENGTH.default\n\t\t_options.salt\t\t= Math.min( Math.max( _options.salt, Cipher.SALT_LENGTH.min ), Cipher.SALT_LENGTH.max )\n\t\t_options.authTag\t= Math.min( Math.max( _options.authTag, Cipher.AUTH_TAG_LENGTH.min ), Cipher.AUTH_TAG_LENGTH.max )\n\t\tif ( ! _options.aad ) {\n\t\t\t_options.aadLength\t= Math.min( Math.max( _options.aadLength, Cipher.AAD_LENGTH.min ), Cipher.AAD_LENGTH.max )\n\t\t}\n\n\t\tconst { keyLength, algorithm } = Cipher.getKeyLength( options.algorithm )\n\n\t\t_options.algorithm\t= algorithm\n\t\t_options.length\t\t= keyLength\n\t\t_options.iv\t\t\t= Cipher.getIVLength( algorithm, options )\n\n\t\treturn _options\n\t}\n\n\n\t/**\n\t * Get the Initialization Vector length based on the given algorithm.\n\t * \n\t * @param\talgorithm The algorithm in use.\n\t * @param\toptions ( Optional ) Additional options. \n\t * @returns\tThe Initialization Vector length based on the given algorithm\n\t */\n\tprivate static getIVLength(\n\t\talgorithm\t: Cph.Options[ 'algorithm' ] = Cipher.DEFAULT_ALGORITHM.buffer,\n\t\toptions\t\t: Cph.Options = {},\n\t)\n\t{\n\t\tswitch ( algorithm ) {\n\t\t\tcase 'aes-128-ccm':\n\t\t\tcase 'aes-128-ocb':\n\t\t\tcase 'aes-192-ccm':\n\t\t\tcase 'aes-192-ocb':\n\t\t\tcase 'aes-256-ccm':\n\t\t\tcase 'aes-256-ocb':\n\t\t\t\treturn 8\n\t\t\tcase 'chacha20-poly1305':\n\t\t\t\treturn 12\n\t\t\tdefault:\n\t\t\t\treturn (\n\t\t\t\t\tMath.min(\n\t\t\t\t\t\tMath.max(\n\t\t\t\t\t\t\toptions.iv || Cipher.IV_LENGTH.default,\n\t\t\t\t\t\t\tCipher.IV_LENGTH.min\n\t\t\t\t\t\t), Cipher.IV_LENGTH.max\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t}\n\t}\n\n\n\t/**\n\t * Ensure correct key length based on the given algorithm.\n\t *\n\t * @param\talgorithm The AES algorithm name.\n\t * @returns\tAn object with validated `algorithm` and `keyLength`.\n\t */\n\tprivate static getKeyLength(\n\t\talgorithm: Cph.Options[ 'algorithm' ] = Cipher.DEFAULT_ALGORITHM.buffer\n\t)\n\t{\n\t\tswitch ( algorithm ) {\n\t\t\tcase 'chacha20-poly1305':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 256 / 8,\n\t\t\t\t} as const\n\t\t\tcase 'aes-128-cbc':\n\t\t\tcase 'aes-128-ccm':\n\t\t\tcase 'aes-128-gcm':\n\t\t\tcase 'aes-128-ocb':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 128 / 8, // AES-128 needs a 128 bit (16 bytes)\n\t\t\t\t} as const\n\t\t\tcase 'aes-192-cbc':\n\t\t\tcase 'aes-192-ccm':\n\t\t\tcase 'aes-192-gcm':\n\t\t\tcase 'aes-192-ocb':\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 192 / 8, // AES-192 needs a 192 bit (24 bytes)\n\t\t\t\t} as const\n\t\t\tcase 'aes-256-cbc':\n\t\t\tcase 'aes-256-ccm':\n\t\t\tcase 'aes-256-gcm':\n\t\t\tcase 'aes-256-ocb':\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\talgorithm: algorithm,\n\t\t\t\t\tkeyLength: 256 / 8, // AES-256 needs a 256 bit (32 bytes)\n\t\t\t\t} as const\n\t\t}\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-GCM algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-GCM algorithm. `false` otherwise.\n\t */\n\tstatic isGCM( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherGCMTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-gcm' ||\n\t\t\talgorithm === 'aes-192-gcm' ||\n\t\t\talgorithm === 'aes-256-gcm'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-CCM algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-CCM algorithm. `false` otherwise.\n\t */\n\tstatic isCCM( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherCCMTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-ccm' ||\n\t\t\talgorithm === 'aes-192-ccm' ||\n\t\t\talgorithm === 'aes-256-ccm' ||\n\t\t\talgorithm === 'chacha20-poly1305'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-OCB algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-OCB algorithm. `false` otherwise.\n\t */\n\tstatic isOCB( algorithm: Cph.AesAlgorithm ): algorithm is crypto.CipherOCBTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-ocb' ||\n\t\t\talgorithm === 'aes-192-ocb' ||\n\t\t\talgorithm === 'aes-256-ocb'\n\t\t)\n\t}\n\n\n\t/**\n\t * Check if the given algorithm is a Cipher AES-CBC algorithm.\n\t * \n\t * @param algorithm The AES Algorithm to check.\n\t * @returns `true` if the given algorithm is a Cipher AES-CBC algorithm. `false` otherwise.\n\t */\n\tstatic isCBC( algorithm: Cph.AesAlgorithm ): algorithm is Cph.CBCTypes\n\t{\n\t\treturn (\n\t\t\talgorithm === 'aes-128-cbc' ||\n\t\t\talgorithm === 'aes-192-cbc' ||\n\t\t\talgorithm === 'aes-256-cbc'\n\t\t)\n\t}\n}"]}
package/dist/types.d.mts CHANGED
@@ -48,6 +48,15 @@ declare namespace Cph {
48
48
  * Resolved Stream Encrypt options (symmetric and hybrid).
49
49
  */
50
50
  type EncryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.EncryptOptions>);
51
+ /**
52
+ * Returnign object from `Cipher.encryptStream()` method.
53
+ */
54
+ interface EncryptReturnType {
55
+ /** The `crypto.Cipher` instance. */
56
+ cipher: crypto.Cipher;
57
+ /** The actual `encrypt` callback that must be called and awaited in order to start the encryption process. */
58
+ encrypt: () => Promise<void>;
59
+ }
51
60
  /**
52
61
  * Options for decrypting a stream (symmetric).
53
62
  */
@@ -61,6 +70,12 @@ declare namespace Cph {
61
70
  * Resolved Stream Decrypt options (symmetric).
62
71
  */
63
72
  type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.DecryptOptions>);
73
+ interface DecryptReturnType {
74
+ /** The `crypto.Decipher` instance. */
75
+ decipher: crypto.Decipher;
76
+ /** The actual `decrypt` callback that must be called and awaited in order to start the decryption process. */
77
+ decrypt: () => Promise<void>;
78
+ }
64
79
  }
65
80
  namespace Hybrid {
66
81
  /**
@@ -82,6 +97,14 @@ declare namespace Cph {
82
97
  * Resolved Stream Decrypt options.
83
98
  */
84
99
  type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Hybrid.DecryptOptions>);
100
+ /**
101
+ * Alias for {@link Cph.Stream.Symmetric.EncryptReturnType}
102
+ */
103
+ type EncryptReturnType = Cph.Stream.Symmetric.EncryptReturnType;
104
+ /**
105
+ * Alias for {@link Cph.Stream.Symmetric.DecryptReturnType}
106
+ */
107
+ type DecryptReturnType = Cph.Stream.Symmetric.DecryptReturnType;
85
108
  }
86
109
  }
87
110
  }
package/dist/types.d.ts CHANGED
@@ -48,6 +48,15 @@ declare namespace Cph {
48
48
  * Resolved Stream Encrypt options (symmetric and hybrid).
49
49
  */
50
50
  type EncryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.EncryptOptions>);
51
+ /**
52
+ * Returnign object from `Cipher.encryptStream()` method.
53
+ */
54
+ interface EncryptReturnType {
55
+ /** The `crypto.Cipher` instance. */
56
+ cipher: crypto.Cipher;
57
+ /** The actual `encrypt` callback that must be called and awaited in order to start the encryption process. */
58
+ encrypt: () => Promise<void>;
59
+ }
51
60
  /**
52
61
  * Options for decrypting a stream (symmetric).
53
62
  */
@@ -61,6 +70,12 @@ declare namespace Cph {
61
70
  * Resolved Stream Decrypt options (symmetric).
62
71
  */
63
72
  type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.DecryptOptions>);
73
+ interface DecryptReturnType {
74
+ /** The `crypto.Decipher` instance. */
75
+ decipher: crypto.Decipher;
76
+ /** The actual `decrypt` callback that must be called and awaited in order to start the decryption process. */
77
+ decrypt: () => Promise<void>;
78
+ }
64
79
  }
65
80
  namespace Hybrid {
66
81
  /**
@@ -82,6 +97,14 @@ declare namespace Cph {
82
97
  * Resolved Stream Decrypt options.
83
98
  */
84
99
  type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Hybrid.DecryptOptions>);
100
+ /**
101
+ * Alias for {@link Cph.Stream.Symmetric.EncryptReturnType}
102
+ */
103
+ type EncryptReturnType = Cph.Stream.Symmetric.EncryptReturnType;
104
+ /**
105
+ * Alias for {@link Cph.Stream.Symmetric.DecryptReturnType}
106
+ */
107
+ type DecryptReturnType = Cph.Stream.Symmetric.DecryptReturnType;
85
108
  }
86
109
  }
87
110
  }
package/dist/types.js CHANGED
@@ -1 +1,2 @@
1
- 'use strict';
1
+ 'use strict';//# sourceMappingURL=types.js.map
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"types.js"}
package/dist/types.mjs CHANGED
@@ -0,0 +1,2 @@
1
+ //# sourceMappingURL=types.mjs.map
2
+ //# sourceMappingURL=types.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"types.mjs"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alessiofrittoli/crypto-cipher",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Node.js Cipher cryptograph utility library",
5
5
  "author": {
6
6
  "name": "Alessio Frittoli",
@@ -71,7 +71,7 @@
71
71
  "@eslint/js": "^9.18.0",
72
72
  "@jest/globals": "^29.7.0",
73
73
  "@types/jest": "^29.5.14",
74
- "@types/node": "^22.10.6",
74
+ "@types/node": "^22.10.7",
75
75
  "concurrently": "^9.1.2",
76
76
  "dotenv": "^16.4.7",
77
77
  "eslint": "^9.18.0",