@alessiofrittoli/crypto-cipher
Version:
Node.js Cipher cryptograph utility library
365 lines (361 loc) • 13.7 kB
TypeScript
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<T extends Cph.AesAlgorithm = Cph.AesAlgorithm> {
/** 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<T extends Cph.AesAlgorithm = Cph.AesAlgorithm> extends Cph.Options<T> {
secret?: CoerceToUint8ArrayInput;
}
/**
* Resolved Common options.
*/
interface ResolvedOptions<T extends Cph.AesAlgorithm = Cph.AesAlgorithm> extends Required<Omit<Cph.Options<T>, '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<Cph.Options<Cph.CBCTypes>, '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<Cph.Stream.EncryptOptions>);
/**
* Resolved Stream Decrypt options.
*
*/
type DecryptResolvedOptions = (Cph.ResolvedOptions & Required<Cph.Stream.DecryptOptions>);
/**
* 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<ArrayBuffer>;
/**
* 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<ArrayBuffer>;
/**
* 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<ArrayBuffer>;
/**
* 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<ArrayBuffer>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
/**
* 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<void>;
};
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 };