@alessiofrittoli/crypto-cipher 2.1.0 → 3.0.0-alpha.1
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 +286 -282
- package/dist/index.d.mts +36 -13
- package/dist/index.d.ts +36 -13
- package/dist/index.js +1 -2
- package/dist/index.mjs +1 -2
- package/dist/types.d.mts +4 -4
- package/dist/types.d.ts +4 -4
- package/dist/types.js +1 -2
- package/dist/types.mjs +0 -2
- package/package.json +37 -32
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/types.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -54,7 +54,7 @@ declare class Cipher {
|
|
|
54
54
|
/**
|
|
55
55
|
* Encrypt in-memory data buffer.
|
|
56
56
|
*
|
|
57
|
-
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.
|
|
57
|
+
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.hybridStreamEncrypt()} methods for large data encryption.
|
|
58
58
|
*
|
|
59
59
|
* @param data The data to encrypt.
|
|
60
60
|
* @param secret The secret key used to encrypt the `data`.
|
|
@@ -65,7 +65,7 @@ declare class Cipher {
|
|
|
65
65
|
/**
|
|
66
66
|
* Decrypt in-memory data buffer.
|
|
67
67
|
*
|
|
68
|
-
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.
|
|
68
|
+
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.hybridStreamDecrypt()} methods for large data decryption.
|
|
69
69
|
*
|
|
70
70
|
* @param data The data to decrypt.
|
|
71
71
|
* @param secret The secret key used to decrypt the `data`.
|
|
@@ -81,7 +81,7 @@ declare class Cipher {
|
|
|
81
81
|
* @param secret The secret key used to encrypt the `data`.
|
|
82
82
|
* @param options Additional options.
|
|
83
83
|
* @returns An object containing:
|
|
84
|
-
* - a new instance of `crypto.
|
|
84
|
+
* - a new instance of `crypto.Cipheriv` allowing you to add listeners to the `cipher` encryption process.
|
|
85
85
|
* - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
|
|
86
86
|
*/
|
|
87
87
|
static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Cph.Stream.Symmetric.EncryptReturnType;
|
|
@@ -93,10 +93,33 @@ declare class Cipher {
|
|
|
93
93
|
* @param secret The secret key used to encrypt the `data`.
|
|
94
94
|
* @param options Additional options.
|
|
95
95
|
* @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
|
|
96
|
-
* - a new instance of `crypto.
|
|
96
|
+
* - a new instance of `crypto.Decipheriv` allowing you to add listeners to the `decipher` decryption process.
|
|
97
97
|
* - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
|
|
98
98
|
*/
|
|
99
99
|
static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<Cph.Stream.Symmetric.DecryptReturnType>;
|
|
100
|
+
/**
|
|
101
|
+
* Encrypt data using hybrid encryption.
|
|
102
|
+
*
|
|
103
|
+
* @param data The data to encrypt.
|
|
104
|
+
* @param publicKey The public key.
|
|
105
|
+
* @param options ( Optional ) Additional options.
|
|
106
|
+
*
|
|
107
|
+
* @returns The encrypted result Buffer.
|
|
108
|
+
*/
|
|
109
|
+
static hybridEncrypt(data: CoerceToUint8ArrayInput, publicKey: crypto.KeyLike, options?: Cph.Options): Buffer<ArrayBuffer>;
|
|
110
|
+
/**
|
|
111
|
+
* Decrypt data using hybrid decryption.
|
|
112
|
+
*
|
|
113
|
+
* @param data The encrypted data to decrypt.
|
|
114
|
+
* @param privateKey The private key.
|
|
115
|
+
* @param options ( Optional ) Additional options.
|
|
116
|
+
*
|
|
117
|
+
* @returns The encrypted result Buffer.
|
|
118
|
+
*/
|
|
119
|
+
static hybridDecrypt(data: CoerceToUint8ArrayInput, privateKey: crypto.KeyLike | {
|
|
120
|
+
key: crypto.KeyLike;
|
|
121
|
+
passphrase?: string;
|
|
122
|
+
}, options?: Cph.Options): Buffer<ArrayBufferLike>;
|
|
100
123
|
/**
|
|
101
124
|
* Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.
|
|
102
125
|
*
|
|
@@ -106,10 +129,10 @@ declare class Cipher {
|
|
|
106
129
|
* @param publicKey The RSA public key used to encrypt the symmetric key.
|
|
107
130
|
* @param options Options for the stream encryption.
|
|
108
131
|
* @returns An object containing:
|
|
109
|
-
* - a new instance of `crypto.
|
|
132
|
+
* - a new instance of `crypto.Cipheriv` allowing you to add listeners to the `cipher` encryption process.
|
|
110
133
|
* - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
|
|
111
134
|
*/
|
|
112
|
-
static
|
|
135
|
+
static hybridStreamEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Cph.Stream.Hybrid.EncryptReturnType;
|
|
113
136
|
/**
|
|
114
137
|
* Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.
|
|
115
138
|
*
|
|
@@ -118,10 +141,10 @@ declare class Cipher {
|
|
|
118
141
|
* @param privateKey The RSA private key used to decrypt the symmetric key.
|
|
119
142
|
* @param options Options for the stream decryption.
|
|
120
143
|
* @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
|
|
121
|
-
* - a new instance of `crypto.
|
|
144
|
+
* - a new instance of `crypto.Decipheriv` allowing you to add listeners to the `decipher` decryption process.
|
|
122
145
|
* - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
|
|
123
146
|
*/
|
|
124
|
-
static
|
|
147
|
+
static hybridStreamDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<Cph.Stream.Hybrid.DecryptReturnType>;
|
|
125
148
|
/**
|
|
126
149
|
* Handle pipe flow to encrypt a Stream.
|
|
127
150
|
*
|
|
@@ -143,7 +166,7 @@ declare class Cipher {
|
|
|
143
166
|
* @param keyLength The encrypted key length in bytes. This is used to properly extract the encrypted Cipher Key and Initialization Vector.
|
|
144
167
|
* @returns A new Promise that resolve a tuple containing the Cipher Encrypted Symmetric Key and Initialization Vector once fulfilled.
|
|
145
168
|
*/
|
|
146
|
-
private static
|
|
169
|
+
private static ExtractKeyIVFromStream;
|
|
147
170
|
/**
|
|
148
171
|
* Generates a `Scrypt` Symmetric Key and the Initialization Vector with the given options.
|
|
149
172
|
*
|
|
@@ -154,10 +177,10 @@ declare class Cipher {
|
|
|
154
177
|
*/
|
|
155
178
|
static newKeyIV<T extends Cph.ResolvedOptions = Cph.ResolvedOptions>(secret: CoerceToUint8ArrayInput, options?: Cph.Options): {
|
|
156
179
|
options: T;
|
|
157
|
-
Key:
|
|
158
|
-
IV:
|
|
159
|
-
AAD: Uint8Array<ArrayBufferLike> |
|
|
160
|
-
salt:
|
|
180
|
+
Key: NonSharedBuffer;
|
|
181
|
+
IV: NonSharedBuffer;
|
|
182
|
+
AAD: Uint8Array<ArrayBufferLike> | NonSharedBuffer;
|
|
183
|
+
salt: NonSharedBuffer;
|
|
161
184
|
};
|
|
162
185
|
/**
|
|
163
186
|
* Resolves the given `options` with `Cipher` defaults and constraints.
|
package/dist/index.d.ts
CHANGED
|
@@ -54,7 +54,7 @@ declare class Cipher {
|
|
|
54
54
|
/**
|
|
55
55
|
* Encrypt in-memory data buffer.
|
|
56
56
|
*
|
|
57
|
-
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.
|
|
57
|
+
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamEncrypt()} or {@link Cipher.hybridStreamEncrypt()} methods for large data encryption.
|
|
58
58
|
*
|
|
59
59
|
* @param data The data to encrypt.
|
|
60
60
|
* @param secret The secret key used to encrypt the `data`.
|
|
@@ -65,7 +65,7 @@ declare class Cipher {
|
|
|
65
65
|
/**
|
|
66
66
|
* Decrypt in-memory data buffer.
|
|
67
67
|
*
|
|
68
|
-
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.
|
|
68
|
+
* ⚠️ This is not suitable for large data. Use {@link Cipher.streamDecrypt()} or {@link Cipher.hybridStreamDecrypt()} methods for large data decryption.
|
|
69
69
|
*
|
|
70
70
|
* @param data The data to decrypt.
|
|
71
71
|
* @param secret The secret key used to decrypt the `data`.
|
|
@@ -81,7 +81,7 @@ declare class Cipher {
|
|
|
81
81
|
* @param secret The secret key used to encrypt the `data`.
|
|
82
82
|
* @param options Additional options.
|
|
83
83
|
* @returns An object containing:
|
|
84
|
-
* - a new instance of `crypto.
|
|
84
|
+
* - a new instance of `crypto.Cipheriv` allowing you to add listeners to the `cipher` encryption process.
|
|
85
85
|
* - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
|
|
86
86
|
*/
|
|
87
87
|
static streamEncrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.EncryptOptions): Cph.Stream.Symmetric.EncryptReturnType;
|
|
@@ -93,10 +93,33 @@ declare class Cipher {
|
|
|
93
93
|
* @param secret The secret key used to encrypt the `data`.
|
|
94
94
|
* @param options Additional options.
|
|
95
95
|
* @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
|
|
96
|
-
* - a new instance of `crypto.
|
|
96
|
+
* - a new instance of `crypto.Decipheriv` allowing you to add listeners to the `decipher` decryption process.
|
|
97
97
|
* - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
|
|
98
98
|
*/
|
|
99
99
|
static streamDecrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.Symmetric.DecryptOptions): Promise<Cph.Stream.Symmetric.DecryptReturnType>;
|
|
100
|
+
/**
|
|
101
|
+
* Encrypt data using hybrid encryption.
|
|
102
|
+
*
|
|
103
|
+
* @param data The data to encrypt.
|
|
104
|
+
* @param publicKey The public key.
|
|
105
|
+
* @param options ( Optional ) Additional options.
|
|
106
|
+
*
|
|
107
|
+
* @returns The encrypted result Buffer.
|
|
108
|
+
*/
|
|
109
|
+
static hybridEncrypt(data: CoerceToUint8ArrayInput, publicKey: crypto.KeyLike, options?: Cph.Options): Buffer<ArrayBuffer>;
|
|
110
|
+
/**
|
|
111
|
+
* Decrypt data using hybrid decryption.
|
|
112
|
+
*
|
|
113
|
+
* @param data The encrypted data to decrypt.
|
|
114
|
+
* @param privateKey The private key.
|
|
115
|
+
* @param options ( Optional ) Additional options.
|
|
116
|
+
*
|
|
117
|
+
* @returns The encrypted result Buffer.
|
|
118
|
+
*/
|
|
119
|
+
static hybridDecrypt(data: CoerceToUint8ArrayInput, privateKey: crypto.KeyLike | {
|
|
120
|
+
key: crypto.KeyLike;
|
|
121
|
+
passphrase?: string;
|
|
122
|
+
}, options?: Cph.Options): Buffer<ArrayBufferLike>;
|
|
100
123
|
/**
|
|
101
124
|
* Encrypt a `Readable` to a `Writable` Stream with hybird Encryption.
|
|
102
125
|
*
|
|
@@ -106,10 +129,10 @@ declare class Cipher {
|
|
|
106
129
|
* @param publicKey The RSA public key used to encrypt the symmetric key.
|
|
107
130
|
* @param options Options for the stream encryption.
|
|
108
131
|
* @returns An object containing:
|
|
109
|
-
* - a new instance of `crypto.
|
|
132
|
+
* - a new instance of `crypto.Cipheriv` allowing you to add listeners to the `cipher` encryption process.
|
|
110
133
|
* - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.
|
|
111
134
|
*/
|
|
112
|
-
static
|
|
135
|
+
static hybridStreamEncrypt(secret: CoerceToUint8ArrayInput, publicKey: crypto.RsaPublicKey | crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.EncryptOptions): Cph.Stream.Hybrid.EncryptReturnType;
|
|
113
136
|
/**
|
|
114
137
|
* Decrypt a `Readable` to a `Writable` Stream with hybrid Decryption.
|
|
115
138
|
*
|
|
@@ -118,10 +141,10 @@ declare class Cipher {
|
|
|
118
141
|
* @param privateKey The RSA private key used to decrypt the symmetric key.
|
|
119
142
|
* @param options Options for the stream decryption.
|
|
120
143
|
* @returns A new Promise that resolves when Key IV extraction completes returning an object containing:
|
|
121
|
-
* - a new instance of `crypto.
|
|
144
|
+
* - a new instance of `crypto.Decipheriv` allowing you to add listeners to the `decipher` decryption process.
|
|
122
145
|
* - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.
|
|
123
146
|
*/
|
|
124
|
-
static
|
|
147
|
+
static hybridStreamDecrypt(privateKey: crypto.RsaPrivateKey | crypto.KeyLike, options: Cph.Stream.Hybrid.DecryptOptions): Promise<Cph.Stream.Hybrid.DecryptReturnType>;
|
|
125
148
|
/**
|
|
126
149
|
* Handle pipe flow to encrypt a Stream.
|
|
127
150
|
*
|
|
@@ -143,7 +166,7 @@ declare class Cipher {
|
|
|
143
166
|
* @param keyLength The encrypted key length in bytes. This is used to properly extract the encrypted Cipher Key and Initialization Vector.
|
|
144
167
|
* @returns A new Promise that resolve a tuple containing the Cipher Encrypted Symmetric Key and Initialization Vector once fulfilled.
|
|
145
168
|
*/
|
|
146
|
-
private static
|
|
169
|
+
private static ExtractKeyIVFromStream;
|
|
147
170
|
/**
|
|
148
171
|
* Generates a `Scrypt` Symmetric Key and the Initialization Vector with the given options.
|
|
149
172
|
*
|
|
@@ -154,10 +177,10 @@ declare class Cipher {
|
|
|
154
177
|
*/
|
|
155
178
|
static newKeyIV<T extends Cph.ResolvedOptions = Cph.ResolvedOptions>(secret: CoerceToUint8ArrayInput, options?: Cph.Options): {
|
|
156
179
|
options: T;
|
|
157
|
-
Key:
|
|
158
|
-
IV:
|
|
159
|
-
AAD: Uint8Array<ArrayBufferLike> |
|
|
160
|
-
salt:
|
|
180
|
+
Key: NonSharedBuffer;
|
|
181
|
+
IV: NonSharedBuffer;
|
|
182
|
+
AAD: Uint8Array<ArrayBufferLike> | NonSharedBuffer;
|
|
183
|
+
salt: NonSharedBuffer;
|
|
161
184
|
};
|
|
162
185
|
/**
|
|
163
186
|
* Resolves the given `options` with `Cipher` defaults and constraints.
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _crypto = require('crypto'); var _crypto2 = _interopRequireDefault(_crypto);var _stream = require('stream');var _conversion = require('@alessiofrittoli/crypto-buffer/conversion');var _coercion = require('@alessiofrittoli/crypto-buffer/coercion');var a=class a{static encrypt(r,e,i={}){let t=_coercion.coerceToUint8Array.call(void 0, r),{salt:s,Key:c,IV:n,AAD:p,options:{algorithm:o,authTag:h}}=a.newKeyIV(e,i);if(a.isCBC(o)){let f=_crypto2.default.createCipheriv(o,c,n),l=Buffer.concat([f.update(t),f.final()]);return Buffer.concat([s,n,l])}let u=_crypto2.default.createCipheriv(o,c,n,{authTagLength:h});a.isCCM(o)&&u.setAAD(p,{plaintextLength:t.length}),(a.isGCM(o)||a.isOCB(o))&&u.setAAD(p);let m=Buffer.concat([u.update(t),u.final()]),d=u.getAuthTag();return Buffer.concat([s,n,p,d,m])}static decrypt(r,e,i={}){let t=_coercion.coerceToUint8Array.call(void 0, r),s=_coercion.coerceToUint8Array.call(void 0, e),c=a.resolveOptions(i),{algorithm:n}=c,p=t.subarray(0,c.salt);t=t.subarray(c.salt);let o=t.subarray(0,c.iv);t=t.subarray(c.iv);let h=_crypto2.default.scryptSync(s,p,c.length);if(a.isCBC(n)){let A=_crypto2.default.createDecipheriv(c.algorithm,h,o);return Buffer.concat([A.update(t),A.final()])}let u=c.aadLength,m=c.authTag,d=t.subarray(0,u);t=t.subarray(u);let f=t.subarray(0,m);t=t.subarray(m);let l=_crypto2.default.createDecipheriv(n,h,o,{authTagLength:m});return a.isCCM(n)&&l.setAAD(d,{plaintextLength:t.length}),(a.isGCM(n)||a.isOCB(n))&&l.setAAD(d),l.setAuthTag(f),Buffer.concat([l.update(t),l.final()])}static streamEncrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{Key:i,IV:t,options:{input:s,output:c,algorithm:n,salt:p,iv:o,authTag:h}}=a.newKeyIV(r,e),u=a.encrypt(Buffer.concat([i,t]),r,{algorithm:n,salt:p,iv:o,authTag:h}),m=_crypto2.default.createCipheriv(n,i,t);return{cipher:m,encrypt:()=>a.stream({cipher:m,input:s,output:c,encryptedKey:u})}}static streamDecrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{input:i,output:t,algorithm:s,salt:c,iv:n,authTag:p,length:o}=a.resolveOptions(e),h=o+n+c+n+p;return a.ExtractKeyIVFromStream(i,h).then(([u,m])=>{if(m.errored)throw m.errored;let d=a.decrypt(u,r,{algorithm:s,salt:c,iv:n,authTag:p}),f=d.subarray(0,o),l=d.subarray(o),A=_crypto2.default.createDecipheriv(s,f,l);return{decipher:A,decrypt:()=>a.decipherStream({decipher:A,input:m,output:t})}})}static hybridEncrypt(r,e,i){let t=_crypto2.default.randomBytes(32),s=_crypto2.default.publicEncrypt({key:e,padding:_crypto2.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},t);return Buffer.concat([_conversion.writeUint16BE.call(void 0, s.length),s,a.encrypt(r,t,i)])}static hybridDecrypt(r,e,i){let t=Buffer.from(_coercion.coerceToUint8Array.call(void 0, r)),s=_conversion.readUint16BE.call(void 0, t.subarray(0,2)),c=t.subarray(2,2+s),n=t.subarray(2+s),p=typeof e=="object"&&"key"in e?e.key:e,o=typeof e=="object"&&"passphrase"in e?e.passphrase:void 0,h=_crypto2.default.privateDecrypt({key:p,passphrase:o,padding:_crypto2.default.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},c);return a.decrypt(n,h,i)}static hybridStreamEncrypt(r,e,i){i.algorithm||(i.algorithm=a.DEFAULT_ALGORITHM.stream);let{Key:t,IV:s,options:{algorithm:c,input:n,output:p}}=a.newKeyIV(r,i),o=_crypto2.default.publicEncrypt(e,Buffer.concat([t,s])),h=_crypto2.default.createCipheriv(c,t,s);return{cipher:h,encrypt:()=>a.stream({cipher:h,input:n,output:p,encryptedKey:o})}}static hybridStreamDecrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{input:i,output:t,algorithm:s,length:c,rsaKeyLength:n}=a.resolveOptions(e);return a.ExtractKeyIVFromStream(i,n).then(([p,o])=>{let h=_crypto2.default.privateDecrypt(r,p),u=h.subarray(0,c),m=h.subarray(c),d=_crypto2.default.createDecipheriv(s,u,m);return{decipher:d,decrypt:()=>a.decipherStream({decipher:d,input:o,output:t})}})}static stream(r){let{cipher:e,encryptedKey:i,input:t,output:s}=r;return new Promise((c,n)=>{e.on("error",n),t.on("error",n),s.on("error",n),s.on("finish",c),s.write(i),t.pipe(e).pipe(s)})}static decipherStream(r){let{decipher:e,input:i,output:t}=r;return new Promise((s,c)=>{e.on("error",c),i.on("error",c),t.on("error",c),t.on("finish",s),i.pipe(e).pipe(t)})}static ExtractKeyIVFromStream(r,e){return new Promise((i,t)=>{let s=Buffer.alloc(0),c=0,n=!1,p=new (0, _stream.Transform)({async transform(o,h,u){if(s.length<e&&(s=Buffer.concat([s,o])),c+=o.length,s.length>e){let m=Math.max(0,s.length-e);s=s.subarray(0,e);let d=o.subarray(m*-1);return n||(i([s,this]),n=!0),this.push(d,h),u()}return c>e&&(n||(i([s,this]),n=!0),this.push(o,h)),u()},final(o){return s.length<e?o(new Error("The extracted KeyIV length is less than the expected length.")):o()}});p.on("error",t),r.on("error",o=>{p.destroy(o),t(o)}),r.pipe(p)})}static newKeyIV(r,e={}){let i=_coercion.coerceToUint8Array.call(void 0, r),t=a.resolveOptions(e),s=_crypto2.default.randomBytes(t.salt),c=_crypto2.default.scryptSync(i,s,t.length),n=_crypto2.default.randomBytes(t.iv),p=t.aad||_crypto2.default.scryptSync(c,s,t.aadLength);return{options:t,Key:c,IV:n,AAD:p,salt:s}}static resolveOptions(r={}){let e={...r};e.aad&&(e.aad=_coercion.coerceToUint8Array.call(void 0, e.aad)),e.salt||(e.salt=a.SALT_LENGTH.default),e.authTag||(e.authTag=a.AUTH_TAG_LENGTH.default),e.aadLength=_optionalChain([e, 'access', _ => _.aad, 'optionalAccess', _2 => _2.length])||e.aadLength||a.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,a.SALT_LENGTH.min),a.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,a.AUTH_TAG_LENGTH.min),a.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,a.AAD_LENGTH.min),a.AAD_LENGTH.max));let{keyLength:i,algorithm:t}=a.getKeyLength(r.algorithm);return e.algorithm=t,e.length=i,e.iv=a.getIVLength(t,r),e}static getIVLength(r=a.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||a.IV_LENGTH.default,a.IV_LENGTH.min),a.IV_LENGTH.max)}}static getKeyLength(r=a.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"}};a.SALT_LENGTH={min:16,max:64,default:32},a.IV_LENGTH={min:8,max:32,default:16},a.AUTH_TAG_LENGTH={min:4,max:16,default:16},a.AAD_LENGTH={min:16,max:128,default:32},a.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},a.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 g=a;exports.Cipher = g;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import y from"crypto";import{Transform as C}from"stream";import{writeUint16BE as b,readUint16BE as L}from"@alessiofrittoli/crypto-buffer/conversion";import{coerceToUint8Array as T}from"@alessiofrittoli/crypto-buffer/coercion";var a=class a{static encrypt(r,e,i={}){let t=T(r),{salt:s,Key:c,IV:n,AAD:p,options:{algorithm:o,authTag:h}}=a.newKeyIV(e,i);if(a.isCBC(o)){let f=y.createCipheriv(o,c,n),l=Buffer.concat([f.update(t),f.final()]);return Buffer.concat([s,n,l])}let u=y.createCipheriv(o,c,n,{authTagLength:h});a.isCCM(o)&&u.setAAD(p,{plaintextLength:t.length}),(a.isGCM(o)||a.isOCB(o))&&u.setAAD(p);let m=Buffer.concat([u.update(t),u.final()]),d=u.getAuthTag();return Buffer.concat([s,n,p,d,m])}static decrypt(r,e,i={}){let t=T(r),s=T(e),c=a.resolveOptions(i),{algorithm:n}=c,p=t.subarray(0,c.salt);t=t.subarray(c.salt);let o=t.subarray(0,c.iv);t=t.subarray(c.iv);let h=y.scryptSync(s,p,c.length);if(a.isCBC(n)){let A=y.createDecipheriv(c.algorithm,h,o);return Buffer.concat([A.update(t),A.final()])}let u=c.aadLength,m=c.authTag,d=t.subarray(0,u);t=t.subarray(u);let f=t.subarray(0,m);t=t.subarray(m);let l=y.createDecipheriv(n,h,o,{authTagLength:m});return a.isCCM(n)&&l.setAAD(d,{plaintextLength:t.length}),(a.isGCM(n)||a.isOCB(n))&&l.setAAD(d),l.setAuthTag(f),Buffer.concat([l.update(t),l.final()])}static streamEncrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{Key:i,IV:t,options:{input:s,output:c,algorithm:n,salt:p,iv:o,authTag:h}}=a.newKeyIV(r,e),u=a.encrypt(Buffer.concat([i,t]),r,{algorithm:n,salt:p,iv:o,authTag:h}),m=y.createCipheriv(n,i,t);return{cipher:m,encrypt:()=>a.stream({cipher:m,input:s,output:c,encryptedKey:u})}}static streamDecrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{input:i,output:t,algorithm:s,salt:c,iv:n,authTag:p,length:o}=a.resolveOptions(e),h=o+n+c+n+p;return a.ExtractKeyIVFromStream(i,h).then(([u,m])=>{if(m.errored)throw m.errored;let d=a.decrypt(u,r,{algorithm:s,salt:c,iv:n,authTag:p}),f=d.subarray(0,o),l=d.subarray(o),A=y.createDecipheriv(s,f,l);return{decipher:A,decrypt:()=>a.decipherStream({decipher:A,input:m,output:t})}})}static hybridEncrypt(r,e,i){let t=y.randomBytes(32),s=y.publicEncrypt({key:e,padding:y.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},t);return Buffer.concat([b(s.length),s,a.encrypt(r,t,i)])}static hybridDecrypt(r,e,i){let t=Buffer.from(T(r)),s=L(t.subarray(0,2)),c=t.subarray(2,2+s),n=t.subarray(2+s),p=typeof e=="object"&&"key"in e?e.key:e,o=typeof e=="object"&&"passphrase"in e?e.passphrase:void 0,h=y.privateDecrypt({key:p,passphrase:o,padding:y.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:"sha256"},c);return a.decrypt(n,h,i)}static hybridStreamEncrypt(r,e,i){i.algorithm||(i.algorithm=a.DEFAULT_ALGORITHM.stream);let{Key:t,IV:s,options:{algorithm:c,input:n,output:p}}=a.newKeyIV(r,i),o=y.publicEncrypt(e,Buffer.concat([t,s])),h=y.createCipheriv(c,t,s);return{cipher:h,encrypt:()=>a.stream({cipher:h,input:n,output:p,encryptedKey:o})}}static hybridStreamDecrypt(r,e){e.algorithm||(e.algorithm=a.DEFAULT_ALGORITHM.stream);let{input:i,output:t,algorithm:s,length:c,rsaKeyLength:n}=a.resolveOptions(e);return a.ExtractKeyIVFromStream(i,n).then(([p,o])=>{let h=y.privateDecrypt(r,p),u=h.subarray(0,c),m=h.subarray(c),d=y.createDecipheriv(s,u,m);return{decipher:d,decrypt:()=>a.decipherStream({decipher:d,input:o,output:t})}})}static stream(r){let{cipher:e,encryptedKey:i,input:t,output:s}=r;return new Promise((c,n)=>{e.on("error",n),t.on("error",n),s.on("error",n),s.on("finish",c),s.write(i),t.pipe(e).pipe(s)})}static decipherStream(r){let{decipher:e,input:i,output:t}=r;return new Promise((s,c)=>{e.on("error",c),i.on("error",c),t.on("error",c),t.on("finish",s),i.pipe(e).pipe(t)})}static ExtractKeyIVFromStream(r,e){return new Promise((i,t)=>{let s=Buffer.alloc(0),c=0,n=!1,p=new C({async transform(o,h,u){if(s.length<e&&(s=Buffer.concat([s,o])),c+=o.length,s.length>e){let m=Math.max(0,s.length-e);s=s.subarray(0,e);let d=o.subarray(m*-1);return n||(i([s,this]),n=!0),this.push(d,h),u()}return c>e&&(n||(i([s,this]),n=!0),this.push(o,h)),u()},final(o){return s.length<e?o(new Error("The extracted KeyIV length is less than the expected length.")):o()}});p.on("error",t),r.on("error",o=>{p.destroy(o),t(o)}),r.pipe(p)})}static newKeyIV(r,e={}){let i=T(r),t=a.resolveOptions(e),s=y.randomBytes(t.salt),c=y.scryptSync(i,s,t.length),n=y.randomBytes(t.iv),p=t.aad||y.scryptSync(c,s,t.aadLength);return{options:t,Key:c,IV:n,AAD:p,salt:s}}static resolveOptions(r={}){let e={...r};e.aad&&(e.aad=T(e.aad)),e.salt||(e.salt=a.SALT_LENGTH.default),e.authTag||(e.authTag=a.AUTH_TAG_LENGTH.default),e.aadLength=e.aad?.length||e.aadLength||a.AAD_LENGTH.default,e.salt=Math.min(Math.max(e.salt,a.SALT_LENGTH.min),a.SALT_LENGTH.max),e.authTag=Math.min(Math.max(e.authTag,a.AUTH_TAG_LENGTH.min),a.AUTH_TAG_LENGTH.max),e.aad||(e.aadLength=Math.min(Math.max(e.aadLength,a.AAD_LENGTH.min),a.AAD_LENGTH.max));let{keyLength:i,algorithm:t}=a.getKeyLength(r.algorithm);return e.algorithm=t,e.length=i,e.iv=a.getIVLength(t,r),e}static getIVLength(r=a.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||a.IV_LENGTH.default,a.IV_LENGTH.min),a.IV_LENGTH.max)}}static getKeyLength(r=a.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"}};a.SALT_LENGTH={min:16,max:64,default:32},a.IV_LENGTH={min:8,max:32,default:16},a.AUTH_TAG_LENGTH={min:4,max:16,default:16},a.AAD_LENGTH={min:16,max:128,default:32},a.DEFAULT_ALGORITHM={buffer:"aes-256-gcm",stream:"aes-256-cbc"},a.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 g=a;export{g as Cipher};
|
package/dist/types.d.mts
CHANGED
|
@@ -55,8 +55,8 @@ declare namespace Cph {
|
|
|
55
55
|
* Returnign object from `Cipher.encryptStream()` method.
|
|
56
56
|
*/
|
|
57
57
|
interface EncryptReturnType {
|
|
58
|
-
/** The `crypto.
|
|
59
|
-
cipher: crypto.
|
|
58
|
+
/** The `crypto.Cipheriv` instance. */
|
|
59
|
+
cipher: crypto.Cipheriv;
|
|
60
60
|
/** The actual `encrypt` callback that must be called and awaited in order to start the encryption process. */
|
|
61
61
|
encrypt: () => Promise<void>;
|
|
62
62
|
}
|
|
@@ -74,8 +74,8 @@ declare namespace Cph {
|
|
|
74
74
|
*/
|
|
75
75
|
type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.DecryptOptions>);
|
|
76
76
|
interface DecryptReturnType {
|
|
77
|
-
/** The `crypto.
|
|
78
|
-
decipher: crypto.
|
|
77
|
+
/** The `crypto.Decipheriv` instance. */
|
|
78
|
+
decipher: crypto.Decipheriv;
|
|
79
79
|
/** The actual `decrypt` callback that must be called and awaited in order to start the decryption process. */
|
|
80
80
|
decrypt: () => Promise<void>;
|
|
81
81
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -55,8 +55,8 @@ declare namespace Cph {
|
|
|
55
55
|
* Returnign object from `Cipher.encryptStream()` method.
|
|
56
56
|
*/
|
|
57
57
|
interface EncryptReturnType {
|
|
58
|
-
/** The `crypto.
|
|
59
|
-
cipher: crypto.
|
|
58
|
+
/** The `crypto.Cipheriv` instance. */
|
|
59
|
+
cipher: crypto.Cipheriv;
|
|
60
60
|
/** The actual `encrypt` callback that must be called and awaited in order to start the encryption process. */
|
|
61
61
|
encrypt: () => Promise<void>;
|
|
62
62
|
}
|
|
@@ -74,8 +74,8 @@ declare namespace Cph {
|
|
|
74
74
|
*/
|
|
75
75
|
type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.Symmetric.DecryptOptions>);
|
|
76
76
|
interface DecryptReturnType {
|
|
77
|
-
/** The `crypto.
|
|
78
|
-
decipher: crypto.
|
|
77
|
+
/** The `crypto.Decipheriv` instance. */
|
|
78
|
+
decipher: crypto.Decipheriv;
|
|
79
79
|
/** The actual `decrypt` callback that must be called and awaited in order to start the decryption process. */
|
|
80
80
|
decrypt: () => Promise<void>;
|
|
81
81
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
//# sourceMappingURL=types.js.map
|
|
1
|
+
"use strict";
|
package/dist/types.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alessiofrittoli/crypto-cipher",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
4
|
"description": "Node.js Cipher cryptograph utility library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Alessio Frittoli",
|
|
@@ -40,25 +40,34 @@
|
|
|
40
40
|
],
|
|
41
41
|
"exports": {
|
|
42
42
|
".": {
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
"import": {
|
|
44
|
+
"types": "./dist/index.d.mts",
|
|
45
|
+
"default": "./dist/index.mjs"
|
|
46
|
+
},
|
|
47
|
+
"require": {
|
|
48
|
+
"types": "./dist/index.d.ts",
|
|
49
|
+
"default": "./dist/index.js"
|
|
50
|
+
}
|
|
46
51
|
},
|
|
47
52
|
"./types": {
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
"import": {
|
|
54
|
+
"types": "./dist/types.d.mts"
|
|
55
|
+
},
|
|
56
|
+
"require": {
|
|
57
|
+
"types": "./dist/types.d.ts"
|
|
58
|
+
}
|
|
51
59
|
}
|
|
52
60
|
},
|
|
53
61
|
"sideEffects": false,
|
|
54
62
|
"scripts": {
|
|
55
63
|
"//1a": "*********************************************************************",
|
|
56
|
-
"//1b": "
|
|
64
|
+
"//1b": "******************** DEV - BUILD - LINT - RELEASE *******************",
|
|
57
65
|
"//1c": "*********************************************************************",
|
|
58
|
-
"
|
|
59
|
-
"build:
|
|
66
|
+
"dev": "cross-env NODE_ENV=development tsup --watch",
|
|
67
|
+
"build:prod": "cross-env NODE_ENV=production tsup",
|
|
68
|
+
"build": "pnpm lint && pnpm test:ci && pnpm build:prod",
|
|
60
69
|
"lint": "eslint",
|
|
61
|
-
"release": "node scripts/
|
|
70
|
+
"release": "node scripts/release.js --verbose --npm",
|
|
62
71
|
"//2a": "*********************************************************************",
|
|
63
72
|
"//2b": "***************************** UNIT TESTS ****************************",
|
|
64
73
|
"//2c": "*********************************************************************",
|
|
@@ -69,7 +78,7 @@
|
|
|
69
78
|
"//3b": "************************ UNIT TESTS COVERAGE ************************",
|
|
70
79
|
"//3c": "*********************************************************************",
|
|
71
80
|
"test:coverage": "pnpm test:watch --coverage",
|
|
72
|
-
"test:ci
|
|
81
|
+
"test:coverage:ci": "pnpm test:ci --coverage",
|
|
73
82
|
"test:serve-coverage": "http-server ./coverage/lcov-report --gzip true -p 0 -o --silent",
|
|
74
83
|
"test:coverage:serve": "concurrently --prefix none --kill-others \"pnpm test:coverage\" \"pnpm test:serve-coverage\"",
|
|
75
84
|
"//4a": "*********************************************************************",
|
|
@@ -83,29 +92,25 @@
|
|
|
83
92
|
"test:misc": "pnpm test:watch misc.test.ts"
|
|
84
93
|
},
|
|
85
94
|
"devDependencies": {
|
|
86
|
-
"@alessiofrittoli/node-scripts": "^
|
|
87
|
-
"@eslint/js": "^9.
|
|
88
|
-
"@jest/globals": "^
|
|
89
|
-
"@types/jest": "^
|
|
90
|
-
"@types/node": "^
|
|
91
|
-
"concurrently": "^9.1
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
+
"@alessiofrittoli/node-scripts": "^3.3.0",
|
|
96
|
+
"@eslint/js": "^9.39.2",
|
|
97
|
+
"@jest/globals": "^30.2.0",
|
|
98
|
+
"@types/jest": "^30.0.0",
|
|
99
|
+
"@types/node": "^25.0.2",
|
|
100
|
+
"concurrently": "^9.2.1",
|
|
101
|
+
"cross-env": "^10.1.0",
|
|
102
|
+
"dotenv": "^17.2.3",
|
|
103
|
+
"eslint": "^9.39.2",
|
|
104
|
+
"globals": "^16.5.0",
|
|
95
105
|
"http-server": "^14.1.1",
|
|
96
|
-
"jest": "^
|
|
97
|
-
"ts-jest": "^29.
|
|
106
|
+
"jest": "^30.2.0",
|
|
107
|
+
"ts-jest": "^29.4.6",
|
|
98
108
|
"ts-node": "^10.9.2",
|
|
99
|
-
"tsup": "^8.
|
|
100
|
-
"typescript": "^5.
|
|
101
|
-
"typescript-eslint": "^8.
|
|
109
|
+
"tsup": "^8.5.1",
|
|
110
|
+
"typescript": "^5.9.3",
|
|
111
|
+
"typescript-eslint": "^8.49.0"
|
|
102
112
|
},
|
|
103
113
|
"dependencies": {
|
|
104
|
-
"@alessiofrittoli/crypto-buffer": "^3.
|
|
105
|
-
},
|
|
106
|
-
"pnpm": {
|
|
107
|
-
"onlyBuiltDependencies": [
|
|
108
|
-
"esbuild"
|
|
109
|
-
]
|
|
114
|
+
"@alessiofrittoli/crypto-buffer": "^3.9.0"
|
|
110
115
|
}
|
|
111
116
|
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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}"]}
|