import crypto, { KeyLike, Cipheriv, Decipheriv } from 'crypto'; import { CoerceToUint8ArrayInput } from '@alessiofrittoli/crypto-buffer'; import { Readable, Writable, Transform } from 'stream'; /** * Cipher types. * */ declare namespace Cph { /** Cipher CBC algorithm types. */ type CBCTypes = 'aes-128-cbc' | 'aes-192-cbc' | 'aes-256-cbc'; /** Cipher supported algorithm types. */ type AesAlgorithm = typeof Cipher.ALGORITHM[keyof typeof Cipher.ALGORITHM]; /** * Common Cipher options. * @template T The AES algorithm type. */ interface Options { /** The Cipher algorithm to use. Default: `aes-256-gcm` | `aes-256-cbc`. */ algorithm?: T; /** The salt length. Minimum: `16`, Maximum: `64`. Default: `32`. */ salt?: number; /** The `IV` length. Minimum: `8`, Maximum: `32`. Default: `16`. */ iv?: number; /** The `authTag` length. Minimum: `4`, Maximum: `16`. Default: `16`. */ authTag?: number; /** Custom `Additional Authenticated Data`. */ aad?: CoerceToUint8ArrayInput; /** The `AAD` length. Minimum: `16`, Maximum: `128`. Default: `32`. */ aadLength?: number; } interface NewKeyIVOptions extends Cph.Options { secret?: CoerceToUint8ArrayInput; } /** * Resolved Common options. */ interface ResolvedOptions extends Required, 'aad'>> { /** The symmetric key length. */ length: number; /** The Additional Authentication Data. */ aad?: Uint8Array; } /** The RSA Private Key. */ type PrivateKey = KeyLike | { key: KeyLike; passphrase?: string; }; namespace Stream { /** * Options for encrypting a stream. * */ interface EncryptOptions extends Pick, 'algorithm'> { /** The `Readable` Stream from where raw data to encrypt is read. */ input: Readable; /** The `Writable` Stream where encrypted data is written. */ output: Writable; } /** * Options for decrypting a stream. * */ type DecryptOptions = Cph.Stream.EncryptOptions; /** * Resolved Stream Encrypt options. * */ type EncryptResolvedOptions = (Cph.ResolvedOptions & Required); /** * Resolved Stream Decrypt options. * */ type DecryptResolvedOptions = (Cph.ResolvedOptions & Required); /** * INTERNAL USE ONLY */ interface CipherOptions { cipher: Cipheriv; encryptedKey?: Buffer; input: Readable; output: Writable; } /** * INTERNAL USE ONLY */ interface DecipherOptions { decipher: Decipheriv; input: Readable; output: Writable; } type ExtractedKeyLength = [KeyLength: number, input: Readable | Transform]; type ExtractedBytes = [DataRead: Buffer, input: Transform]; } namespace Decrypt { interface ExtractKeyOptions { privateKey: Cph.PrivateKey; EncryptedKeyIV: Buffer; keyLength: number; } } } declare class Cipher { /** * Cipher default `salt` lengths. * */ static readonly SALT_LENGTH: { readonly min: 16; readonly max: 64; readonly default: 32; }; /** * Cipher default `IV` lengths. * */ static readonly IV_LENGTH: { readonly min: 8; readonly max: 32; readonly default: 16; }; /** * Cipher default `Auth Tag` lengths. * */ static readonly AUTH_TAG_LENGTH: { readonly min: 4; readonly max: 16; readonly default: 16; }; /** * Cipher default `Additional Authenticated Data` lengths. * */ static readonly AAD_LENGTH: { readonly min: 16; readonly max: 128; readonly default: 32; }; /** * Cipher algorithm name. * */ static readonly ALGORITHM: { /** AES 128 bit Cipher Block Chaining. */ readonly AES_128_CBC: "aes-128-cbc"; /** AES 192 bit Cipher Block Chaining. */ readonly AES_192_CBC: "aes-192-cbc"; /** AES 256 bit Cipher Block Chaining. */ readonly AES_256_CBC: "aes-256-cbc"; /** AES 128 bit AEAD Counter with CBC-MAC. */ readonly AES_128_CCM: "aes-128-ccm"; /** AES 192 bit AEAD Counter with CBC-MAC. */ readonly AES_192_CCM: "aes-192-ccm"; /** AES 256 bit AEAD Counter with CBC-MAC. */ readonly AES_256_CCM: "aes-256-ccm"; /** AES 128 bit AEAD Galois/Counter Mode. */ readonly AES_128_GCM: "aes-128-gcm"; /** AES 192 bit AEAD Galois/Counter Mode. */ readonly AES_192_GCM: "aes-192-gcm"; /** AES 256 bit AEAD Galois/Counter Mode. */ readonly AES_256_GCM: "aes-256-gcm"; /** AES 128 bit AEAD Offset Codebook Mode. */ readonly AES_128_OCB: "aes-128-ocb"; /** AES 192 bit AEAD Offset Codebook Mode. */ readonly AES_192_OCB: "aes-192-ocb"; /** AES 256 bit AEAD Offset Codebook Mode. */ readonly AES_256_OCB: "aes-256-ocb"; /** AES 256 bit AEAD. */ readonly CHACHA_20_POLY: "chacha20-poly1305"; }; /** * Default AES algorithms used based on functionality. * */ static readonly DEFAULT_ALGORITHM: { readonly buffer: "aes-256-gcm"; readonly stream: "aes-256-cbc"; }; /** * Supported AES algorithms. * */ static readonly ALGORITHMS: Cph.AesAlgorithm[]; /** * Encrypt in-memory data buffer. * * ⚠️ This is not suitable for large data encryption. Use {@link Cipher.stream.Encrypt()} or {@link Cipher.stream.HybridEncrypt()} methods for large data encryption. * * @param data The data to encrypt. * @param secret The secret key used to encrypt the `data`. * @param options (Optional) Additional options. * @returns The encrypted result Buffer. */ static Encrypt(data: CoerceToUint8ArrayInput, secret: CoerceToUint8ArrayInput, options?: Cph.Options): Buffer; /** * Decrypt in-memory data buffer. * * ⚠️ This is not suitable for large data decryption. Use {@link Cipher.stream.Decrypt()} or {@link Cipher.stream.HybridDecrypt()} methods for large data decryption. * * @param data The data to decrypt. * @param secret The secret key used to decrypt the `data`. * @param options (Optional) Additional options. Must be the same used while encrypting data. * @returns The decrypted data Buffer. */ static Decrypt(data: CoerceToUint8ArrayInput, secret: CoerceToUint8ArrayInput, options?: Cph.Options): Buffer; /** * Encrypt in-memory data using hybrid encryption. * * ⚠️ This is not suitable for large data encryption. Use {@link Cipher.stream.HybridEncrypt()} method for large data encryption. * * @param data The data to encrypt. * @param key The RSA Public Key. * @param options (Optional) Additional options. * * @returns The encrypted result Buffer. */ static HybridEncrypt(data: CoerceToUint8ArrayInput, key: crypto.KeyLike, options?: Cph.Options): Buffer; /** * Decrypt in-memory data using hybrid decryption. * * ⚠️ This is not suitable for large data decryption. Use {@link Cipher.stream.HybridDecrypt()} method for large data decryption. * * @param data The encrypted data to decrypt. * @param key The RSA Private Key. * @param options (Optional) Additional options. * * @returns The encrypted result Buffer. */ static HybridDecrypt(data: CoerceToUint8ArrayInput, key: Cph.PrivateKey, options?: Cph.Options): Buffer; /** * Cipher stream based functions. * */ static stream: { /** * Encrypt stream data. * * @param secret The secret key used to encrypt the data. * @param options An object defining required options. See {@link Cph.Stream.EncryptOptions} for more info. * * @returns A new Promise that resolves `void` once stream encryption is completed. */ Encrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.EncryptOptions): Promise; /** * Decrypt stream data. * * @param secret The secret key used to decrypt the data. * @param options An object defining required options. See {@link Cph.Stream.DecryptOptions} for more info. * * @returns A new Promise that resolves `void` once stream decryption is completed. */ Decrypt(secret: CoerceToUint8ArrayInput, options: Cph.Stream.DecryptOptions): Promise; /** * Encrypt stream data using hybrid encryption. * * @param key The RSA Public Key. * @param options An object defining required options. See {@link Cph.Stream.EncryptOptions} for more info. * * @returns A new Promise that resolves `void` once stream encryption is completed. */ HybridEncrypt(key: crypto.KeyLike, options: Cph.Stream.EncryptOptions): Promise; /** * Decrypt stream data using hybrid decryption. * * @param key The private key. * @param options An object defining required options. See {@link Cph.Stream.DecryptOptions} for more info. * * @returns A new Promise that resolves `void` once stream decryption is completed. */ HybridDecrypt(key: Cph.PrivateKey, options: Cph.Stream.DecryptOptions): Promise; /** * Handle pipe flow to encrypt a Stream. * * @param options Required parameters. * @returns A new Promise that resolves `void` once stream is completed. */ Cipher(options: Cph.Stream.CipherOptions): Promise; /** * Handle pipe flow to decrypt a Stream. * * @param options Required parameters. * @returns A new Promise that resolves `void` once stream is completed. */ Decipher(options: Cph.Stream.DecipherOptions): Promise; }; private static _stream; /** * Decrypt Key and Initialization Vector. * * @param options An object containing required data. * @returns An object containing decrpyted `Key` and `IV`. */ private static DecryptKeyIV; private static GetPrivateKey; /** * Generates a `Scrypt` Symmetric Key and the Initialization Vector with the given options. * * @param options (Optional) Additional options. * * @returns An object with the generated `Key`, `IV`, `salt` and resolved `options`. */ private static NewKeyIV; /** * Resolves the given `options` with `Cipher` defaults and constraints. * * @param options (Optional) Additional options. * @returns The given `options` with `Cipher` defaults and constraints. */ private static ResolveOptions; /** * Get the Initialization Vector length based on the given algorithm. * * @param algorithm The algorithm in use. * @param options (Optional) Additional options. * @returns The Initialization Vector length based on the given algorithm */ private static GetIVLength; /** * Ensure correct key length based on the given algorithm. * * @param algorithm The AES algorithm name. * @returns An object with validated `algorithm` and `keyLength`. */ private static GetKeyLength; /** * Check if the given algorithm is a Cipher AES-GCM algorithm. * * @param algorithm The AES Algorithm to check. * @returns `true` if the given algorithm is a Cipher AES-GCM algorithm. `false` otherwise. */ static IsGCM(algorithm: Cph.AesAlgorithm): algorithm is crypto.CipherGCMTypes; /** * Check if the given algorithm is a Cipher AES-CCM algorithm. * * @param algorithm The AES Algorithm to check. * @returns `true` if the given algorithm is a Cipher AES-CCM algorithm. `false` otherwise. */ static IsCCM(algorithm: Cph.AesAlgorithm): algorithm is crypto.CipherCCMTypes; /** * Check if the given algorithm is a Cipher chacha20-poly1305 algorithm. * * @param algorithm The AES Algorithm to check. * @returns `true` if the given algorithm is a Cipher chacha20-poly1305 algorithm. `false` otherwise. */ static IsChacha20Poly(algorithm: Cph.AesAlgorithm): algorithm is crypto.CipherChaCha20Poly1305Types; /** * Check if the given algorithm is a Cipher AES-OCB algorithm. * * @param algorithm The AES Algorithm to check. * @returns `true` if the given algorithm is a Cipher AES-OCB algorithm. `false` otherwise. */ static IsOCB(algorithm: Cph.AesAlgorithm): algorithm is crypto.CipherOCBTypes; /** * Check if the given algorithm is a Cipher AES-CBC algorithm. * * @param algorithm The AES Algorithm to check. * @returns `true` if the given algorithm is a Cipher AES-CBC algorithm. `false` otherwise. */ static IsCBC(algorithm: Cph.AesAlgorithm): algorithm is Cph.CBCTypes; } export { Cipher as C, Cph };