{"id":26758465,"url":"https://github.com/alessiofrittoli/crypto-cipher","last_synced_at":"2025-12-28T20:51:34.423Z","repository":{"id":272206766,"uuid":"915824915","full_name":"alessiofrittoli/crypto-cipher","owner":"alessiofrittoli","description":"Node.js Cipher cryptograph utility library","archived":false,"fork":false,"pushed_at":"2025-03-22T15:52:56.000Z","size":171,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-22T15:55:13.674Z","etag":null,"topics":["aes-encryption","cipher","encryption","encryption-decryption","stream-encryption"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@alessiofrittoli/crypto-cipher","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alessiofrittoli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"license.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-12T22:25:12.000Z","updated_at":"2025-03-22T15:52:13.000Z","dependencies_parsed_at":"2025-01-12T23:28:23.163Z","dependency_job_id":"5bd0bb7d-4d30-4b23-b790-3441038e1a9a","html_url":"https://github.com/alessiofrittoli/crypto-cipher","commit_stats":null,"previous_names":["alessiofrittoli/crypto-cipher"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-cipher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-cipher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-cipher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alessiofrittoli%2Fcrypto-cipher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alessiofrittoli","download_url":"https://codeload.github.com/alessiofrittoli/crypto-cipher/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246059301,"owners_count":20717085,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-encryption","cipher","encryption","encryption-decryption","stream-encryption"],"created_at":"2025-03-28T16:20:12.378Z","updated_at":"2025-12-28T20:51:34.379Z","avatar_url":"https://github.com/alessiofrittoli.png","language":"TypeScript","funding_links":["https://github.com/sponsors/alessiofrittoli"],"categories":[],"sub_categories":[],"readme":"# Crypto Cipher 🔐\n\n[![NPM Latest Version][version-badge]][npm-url] [![Coverage Status][coverage-badge]][coverage-url] [![Socket Status][socket-badge]][socket-url] [![NPM Monthly Downloads][downloads-badge]][npm-url] [![Dependencies][deps-badge]][deps-url]\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n[version-badge]: https://img.shields.io/npm/v/%40alessiofrittoli%2Fcrypto-cipher\n[npm-url]: https://npmjs.org/package/%40alessiofrittoli%2Fcrypto-cipher\n[coverage-badge]: https://coveralls.io/repos/github/alessiofrittoli/crypto-cipher/badge.svg\n[coverage-url]: https://coveralls.io/github/alessiofrittoli/crypto-cipher\n[socket-badge]: https://socket.dev/api/badge/npm/package/@alessiofrittoli/crypto-cipher\n[socket-url]: https://socket.dev/npm/package/@alessiofrittoli/crypto-cipher/overview\n[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Fcrypto-cipher.svg\n[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Fcrypto-cipher\n[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Fcrypto-cipher\n\n[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23DB61A2\n[sponsor-url]: https://github.com/sponsors/alessiofrittoli\n\n## Node.js Cipher cryptograph utility library\n\n### Table of Contents\n\n- [Getting started](#getting-started)\n- [Key features](#key-features)\n- [API Reference](#api-reference)\n  - [Importing the library](#importing-the-library)\n  - [Constants](#constants)\n  - [Methods](#methods)\n    - [`Cipher.encrypt()`](#cipherencrypt)\n    - [`Cipher.decrypt()`](#cipherdecrypt)\n    - [`Cipher.streamEncrypt()`](#cipherstreamencrypt)\n    - [`Cipher.streamDecrypt()`](#cipherstreamencrypt)\n    - [`Cipher.hybridEncrypt()`](#cipherhybridencrypt)\n    - [`Cipher.hybridDecrypt()`](#cipherhybriddecrypt)\n  - [Types](#types)\n- [Examples](#examples)\n  - [In-memory data buffer encryption/decryption](#in-memory-data-buffer-encryptiondecryption)\n  - [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption)\n  - [In-memory data stream with hybrid encryption/decryption](#in-memory-data-stream-with-hybrid-encryptiondecryption)\n  - [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption)\n  - [File based data stream with hybrid encryption/decryption](#file-based-data-stream-with-hybrid-encryptiondecryption)\n- [Development](#development)\n  - [ESLint](#eslint)\n  - [Jest](#jest)\n- [Contributing](#contributing)\n- [Security](#security)\n- [Credits](#made-with-)\n\n---\n\n### Getting started\n\nThe `crypto-cipher` library provides AES encryption and decryption functionality, supporting both in-memory buffers and streams. It adheres to the [NIST SP 800-38D](https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf) standard recommendations.\n\n⚠️ Note that every performed operation cannot be accomplished client-side and must be executed on a back-end server.\n\nIt is part of the [`crypto`](https://npmjs.com/search?q=%40alessiofrittoli%2Fcrypto) utility libraries and can be installed by running the following command:\n\n```bash\nnpm i @alessiofrittoli/crypto-cipher\n```\n\nor using `pnpm`\n\n```bash\npnpm i @alessiofrittoli/crypto-cipher\n```\n\n---\n\n### Key features\n\n- Supports multiple AES algorithms (`CCM`, `GCM`, `OCB`, `CBC`) and even `chacha20-poly1305`.\n- In-memory buffer encryption and decrpytion.\n- Robust support for encrypting and decrypting streams (in-memory and file based), with seamless handling of key/IV extraction.\n- Hybrid encryption methods for combining symmetric and asymmetric cryptography.\n\n#### Options Management\n\n- A solid options resolver mechanism ensures consistent handling of defaults and constraints.\n\n#### Security Considerations\n\n- Random `salt` and `IV` generation.\n- Authenticated encryption modes with proper `authTag` and `Additional Authenticated Data` handling.\n\n#### Readable and Modular\n\n- Separation of concerns with clear method responsibilities.\n- Comprehensive JSDoc comments enhance maintainability and readability.\n\n---\n\n### API Reference\n\n#### Constants\n\n##### `Cipher.SALT_LENGTH`\n\nDefines the minimum, maximum, and default lengths for salt.\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property   | Value |\n|------------|-------|\n| `min`      | 16    |\n| `max`      | 64    |\n| `default`  | 32    |\n\n\u003c/details\u003e\n\n---\n\n##### `Cipher.IV_LENGTH`\n\nDefines the minimum, maximum, and default lengths for initialization vectors (IV).\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property   | Value |\n|------------|-------|\n| `min`      | 8     |\n| `max`      | 32    |\n| `default`  | 16    |\n\n\u003c/details\u003e\n\n---\n\n##### `Cipher.AUTH_TAG_LENGTH`\n\nDefines the minimum, maximum, and default lengths for authentication tags.\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property   | Value |\n|------------|-------|\n| `min`      | 4     |\n| `max`      | 16    |\n| `default`  | 16    |\n\n\u003c/details\u003e\n\n---\n\n##### `Cipher.AAD_LENGTH`\n\nDefines the minimum, maximum, and default lengths for additional authenticated data (AAD).\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property   | Value |\n|------------|-------|\n| `min`      | 16    |\n| `max`      | 4096  |\n| `default`  | 32    |\n\n\u003c/details\u003e\n\n---\n\n##### `Cipher.DEFAULT_ALGORITHM`\n\nSpecifies default AES algorithms for buffer and stream operations.\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Operation  | Algorithm    | Description |\n|------------|--------------|-------------|\n| `buffer`   | `aes-256-gcm` | Default algorithm used for buffer data encryption/decryption |\n| `stream`   | `aes-256-cbc` | Default algorithm used for stream encryption/decryption |\n\n\u003c/details\u003e\n\n---\n\n##### `Cipher.ALGORITHMS`\n\nSupported AES algorithms:\n\n\u003cdetails\u003e\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n- `aes-128-gcm`\n- `aes-192-gcm`\n- `aes-256-gcm`\n- `aes-128-ccm`\n- `aes-192-ccm`\n- `aes-256-ccm`\n- `aes-128-ocb`\n- `aes-192-ocb`\n- `aes-256-ocb`\n- `aes-128-cbc`\n- `aes-192-cbc`\n- `aes-256-cbc`\n- `chacha20-poly1305`\n\n\u003c/details\u003e\n\n---\n\n#### Methods\n\n##### `Cipher.encrypt()`\n\nEncrypts an in-memory data buffer.\n\n⚠️ This is not suitable for large data.\nUse [`Cipher.streamEncrypt()`](#cipherstreamencrypt) or [`Cipher.hybridEncrypt()`](#cipherhybridencrypt) methods for large data encryption.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name     | Type                    | Description                             |\n|----------|-------------------------|-----------------------------------------|\n| `data`   | `CoerceToUint8ArrayInput` | Data to encrypt.                        |\n| `secret` | `CoerceToUint8ArrayInput` | Secret key for encryption.              |\n| `options`| `Cph.Options`           | (Optional) Additional encryption options.|\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Buffer`\n\n- The encrypted result buffer.\n\n\u003c/details\u003e\n\n---\n\n- See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.\n- See [`Cph.Options`](#cphoptionst) for more informations about additional encryption options.\n- See [In-memory data buffer encryption/decryption](#in-memory-data-buffer-encryptiondecryption) examples.\n\n---\n\n##### `Cipher.decrypt()`\n\nDecrypts an in-memory data buffer.\n\n⚠️ This is not suitable for large data.\nUse [`Cipher.streamDecrypt()`](#cipherstreamdecrypt) or [`Cipher.hybridDecrypt()`](#cipherhybriddecrypt) methods for large data decryption.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name     | Type                    | Description                             |\n|----------|-------------------------|-----------------------------------------|\n| `data`   | `CoerceToUint8ArrayInput` | Data to decrypt.                        |\n| `secret` | `CoerceToUint8ArrayInput` | Secret key for decryption.              |\n| `options`| `Cph.Options`           | (Optional) Decryption options (must match encryption).|\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Buffer`\n\n- The decrypted result buffer.\n\n\u003c/details\u003e\n\n---\n\n- See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.\n- See [`Cph.Options`](#cphoptionst) for more informations about additional decryption options.\n- See [In-memory data buffer encryption/decryption](#in-memory-data-buffer-encryptiondecryption) examples.\n\n---\n\n##### `Cipher.streamEncrypt()`\n\nEncrypts a `Readable` stream to a `Writable` stream.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name      | Type                              | Description                           |\n|-----------|-----------------------------------|---------------------------------------|\n| `secret`  | `CoerceToUint8ArrayInput`         | Secret key for encryption.            |\n| `options` | `Cph.Stream.Symmetric.EncryptOptions` | Stream encryption options.        |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Cph.Stream.Symmetric.EncryptReturnType`\n\n- An object containing:\n  - a new instance of `crypto.Cipher` allowing you to add listeners to the `cipher` encryption process.\n  - the actual `encrypt` callback that must be called and awaited in order to start the encryption process.\n\n\u003c/details\u003e\n\n---\n\n- See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.\n- See [`Cph.Stream.Symmetric.EncryptOptions`](#cphstreamsymmetricencryptoptions) for more informations about encryption options.\n- See [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption) examples.\n- See [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption) examples.\n\n---\n\n##### `Cipher.streamDecrypt()`\n\nDecrypts a `Readable` stream to a `Writable` stream.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name      | Type                              | Description                           |\n|-----------|-----------------------------------|---------------------------------------|\n| `secret`  | `CoerceToUint8ArrayInput`         | Secret key for decryption.            |\n| `options` | `Cph.Stream.Symmetric.DecryptOptions` | Stream decryption options.            |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Promise\u003cCph.Stream.Symmetric.DecryptReturnType\u003e`\n\n- A new Promise that resolves when Key IV extraction completes returning an object containing:\n  - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n  - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\n\u003c/details\u003e\n\n---\n\n- See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.\n- See [`Cph.Stream.Symmetric.DecryptOptions`](#cphstreamsymmetricdecryptoptions) for more informations about decryption options.\n- See [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption) examples.\n- See [File based data stream encryption/decryption](#file-based-data-stream-encryptiondecryption) examples.\n\n---\n\n##### `Cipher.hybridEncrypt()`\n\nEncrypts a stream using hybrid encryption (symmetric + RSA).\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name        | Type                              | Description                           |\n|-------------|-----------------------------------|---------------------------------------|\n| `secret`    | `CoerceToUint8ArrayInput`         | Symmetric secret key.                 |\n| `publicKey` | `crypto.RsaPublicKey \\| crypto.KeyLike` | RSA public key used to encrypt the generated symmetric key. |\n| `options`   | `Cph.Stream.Hybrid.EncryptOptions` | Stream encryption options.        |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Cph.Stream.Hybrid.EncryptReturnType`\n\n- An object containing:\n  - a new instance of `cipher` allowing you to add listeners to the `cipher` encryption process.\n  - the actual `encrypt` callback that must be called and awaited to start the encryption process.\n\n\u003c/details\u003e\n\n---\n\n- See [`CoerceToUint8ArrayInput`](#coercetouint8arrayinput) for more informations about supported input data types.\n- See [`Cph.Stream.Hybrid.EncryptOptions`](#cphstreamhybridencryptoptions) for more informations about encryption options.\n- See [In-memory data stream with hybrid encryption/decryption](#in-memory-data-stream-with-hybrid-encryptiondecryption) examples.\n- See [File based data stream with hybrid encryption/decryption](#file-based-data-stream-with-hybrid-encryptiondecryption) examples.\n\n---\n\n##### `Cipher.hybridDecrypt()`\n\nDecrypts a stream using hybrid decryption (symmetric + RSA).\n\n\u003cdetails\u003e\n\n\u003csummary\u003eParameters\u003c/summary\u003e\n\n| Name         | Type                              | Description                           |\n|--------------|-----------------------------------|---------------------------------------|\n| `privateKey` | `crypto.RsaPrivateKey \\| crypto.KeyLike` | RSA private key for used to decrpyt the encrypted symmetric key. |\n| `options`    | `Cph.Stream.Hybrid.DecryptOptions` | Stream decryption options.           |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eReturns\u003c/summary\u003e\n\nType: `Promise\u003cCph.Stream.Hybrid.DecryptReturnType\u003e`\n\n- A new Promise that resolves when Key IV extraction completes returning an object containing:\n  - a new instance of `crypto.Decipher` allowing you to add listeners to the `decipher` decryption process.\n  - the actual `decrypt` callback that must be called and awaited in order to start the decryption process.\n\n\u003c/details\u003e\n\n---\n\n- See [`Cph.Stream.Hybrid.DecryptOptions`](#cphstreamhybriddecryptoptions) for more informations about decryption options.\n- See [In-memory data stream with hybrid encryption/decryption](#in-memory-data-stream-with-hybrid-encryptiondecryption) examples.\n- See [File based data stream with hybrid encryption/decryption](#file-based-data-stream-with-hybrid-encryptiondecryption) examples.\n\n---\n\n#### Types\n\n##### `CoerceToUint8ArrayInput`\n\nThis module supports different input data types and it uses the [`coerceToUint8Array`](https://npmjs.com/package/@alessiofrittoli/crypto-buffer#coercetouint8array) utility function from [`@alessiofrittoli/crypto-buffer`](https://npmjs.com/package/@alessiofrittoli/crypto-buffer) to convert it to a `Uint8Array`.\n\n- See [`coerceToUint8Array`](https://npmjs.com/package/@alessiofrittoli/crypto-buffer#coercetouint8array) for more informations about the supported input types.\n\n---\n\n##### `Cph.CBCTypes`\n\nCipher CBC algorithm types.\n\n---\n\n##### `Cph.AesAlgorithm`\n\nSupported AES algorithm types.\n\n---\n\n##### `Cph.Options\u003cT\u003e`\n\nCommon options in encryption/decryption processes.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eType parameters\u003c/summary\u003e\n\n| Parameter | Default        | Description |\n|-----------|----------------|-------------|\n| `T`       | `Cph.AesAlgorithm` | Accepted algorithm in `Cph.Options`. This is usefull to constraint specifc algorithms. |\n\n\u003c/details\u003e\n\n---\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property    | Type     | Default       | Description |\n|-------------|----------|---------------|-------------|\n| `algorithm` | `T`      | `aes-256-gcm \\| aes-256-cbc` | Accepted algorithms. |\n| `salt`      | `number` | `32` | The `salt` length in bytes. Minimum: `16`, Maximum: `64`. |\n| `iv`        | `number` | `16` | The Initialization Vector length in bytes. Minimum: `8`, Maximum: `32`. |\n| `authTag`   | `number` | `16` | The `authTag` length in bytes. Minimum: `4`, Maximum: `16`. |\n| `aad`       | `CoerceToUint8ArrayInput` | - | Custom Additional Authenticated Data. `aadLength` is then automatically resolved. If not provided, a random AAD is generated with a max length of `aadLength`. |\n| `aadLength` | `number` | `32` | The auto generated AAD length in bytes. Minimum: `16`, Maximum: `128`. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Symmetric.EncryptOptions`\n\nStream symmetric encryption options.\n\n- Extends [`Cph.Options\u003cCph.CBCTypes\u003e`](#cphoptionst).\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property | Type     | Description |\n|----------|----------|-------------|\n| `input`  | `Readable` | The `Readable` Stream from where raw data to encrypt is read. |\n| `output` | `Writable` | The `Writable` Stream where encrypted data is written. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Symmetric.EncryptReturnType`\n\nReturnign object from `Cipher.streamEncrypt()` method.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property | Type     | Description |\n|----------|----------|-------------|\n| `cipher`  | `crypto.Cipher` | The `crypto.Cipher` instance. |\n| `encrypt` | `() =\u003e Promise\u003cvoid\u003e` | The actual `encrypt` callback that must be called and awaited in order to start the encryption process. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Symmetric.DecryptOptions`\n\nStream symmetric decryption options.\n\n- Extends [`Cph.Stream.Symmetric.EncryptOptions`](#cphstreamsymmetricencryptoptions).\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property | Type     | Description |\n|----------|----------|-------------|\n| `input`  | `Readable` | The `Readable` Stream from where encrypted data is read. |\n| `output` | `Writable` | The `Writable` Stream where decrypted data is written. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Symmetric.DecryptReturnType`\n\nReturnign object from awaited `Cipher.streamDecrypt()` method.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property | Type     | Description |\n|----------|----------|-------------|\n| `decipher` | `crypto.Decipher` | The `crypto.Decipher` instance. |\n| `decrypt` | `() =\u003e Promise\u003cvoid\u003e` | The actual `decrypt` callback that must be called and awaited in order to start the decryption process. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Hybrid.EncryptOptions`\n\nStream hybrid encryption options.\n\n- Alias for [`Cph.Stream.Symmetric.EncryptOptions`](#cphstreamsymmetricencryptoptions)\n\n---\n\n##### `Cph.Stream.Hybrid.EncryptReturnType`\n\nReturnign object from `Cipher.hybridEncrypt()` method.\n\n- Alias for [`Cph.Stream.Symmetric.EncryptReturnType`](#cphstreamsymmetricencryptreturntype)\n\n---\n\n##### `Cph.Stream.Hybrid.DecryptOptions`\n\nStream hybrid decryption options.\n\n- Extends [`Cph.Stream.Symmetric.DecryptOptions`](#cphstreamsymmetricdecryptoptions).\n\n\u003cdetails\u003e\n\n\u003csummary\u003eProperties\u003c/summary\u003e\n\n| Property       | Type     | Description |\n|----------------|----------|-------------|\n| `rsaKeyLength` | `number` | The RSA key length in bytes used while encrypting data. This is used to properly extract the encrypted Cipher Key and Initialization Vector from the encrypted data. |\n\n\u003c/details\u003e\n\n---\n\n##### `Cph.Stream.Hybrid.DecryptReturnType`\n\nReturnign object from awaited `Cipher.hybridDecrypt()` method.\n\n- Alias for [`Cph.Stream.Symmetric.DecryptReturnType`](#cphstreamsymmetricdecryptreturntype)\n\n---\n\n### Examples\n\n#### Importing the library\n\n```ts\nimport { Cipher } from '@alessiofrittoli/crypto-cipher'\nimport type { Cph as CipherTypes } from '@alessiofrittoli/crypto-cipher/types'\n```\n\n#### In-memory data buffer encryption/decryption\n\nThe simpliest way to encrypt/decrypt in-memory data buffers.\n\n```ts\n// encrypt\nconst data      = 'my top-secret data'\nconst password  = 'my-very-strong-password'\n\nconst encrypted = Cipher.encrypt( data, password )\n\n// decrypt\nconst decrypted = Cipher.decrypt( encrypted, password )\nconsole.log( decrypted ) // Outputs: my top-secret data\n```\n\n---\n\n#### In-memory data stream encryption/decryption\n\nThe in-memory data stream comes pretty handy when, for example, we need to stream encrypted data within a Server Response or to decrypt stream data from a Server Response.\n\n##### Streaming\n\n```ts\n// /api/stream-encrypt\n\nimport { Readable, Writable } from 'stream'\n\nconst routeHandler = () =\u003e {\n  const data      = 'my top-secret data'\n  const password  = 'my-very-strong-password'\n  const stream    = new TransformStream()\n  const writer    = stream.writable.getWriter()\n  \n  // Create a `Readable` Stream with raw data.\n  const input = new Readable( {\n    read()\n    {\n      this.push( data )\n      this.push( null ) // Signal end of stream\n    },\n  } )\n      \n  // `Writable` Stream where encrypted data is written\n  const output = new Writable( {\n    write( chunk, encoding, callback )\n    {\n      writer.write( chunk )\n      callback()\n    },\n    final( callback )\n    {\n      writer.close()\n      callback()\n    }\n  } )\n  \n  Cipher.streamEncrypt( password, { input, output } )\n    .encrypt()\n  \n  return (\n    // encrypted stream\n    new Response( stream.readable )\n  )\n}\n```\n\n##### Decrypting received stream\n\n```ts\n// /api/stream-decrypt\n\nimport { Transform, Writable } from 'stream'\nimport { StreamReader } from '@alessiofrittoli/stream-reader'\n\nconst password = 'my-very-strong-password'\n\nconst routeHandler = () =\u003e (\n  fetch( '/api/stream-encrypt' )\n    .then( response =\u003e {\n\n      if ( ! response.body ) {\n        return (\n          new Respone( null, { status: 400 } )\n        )\n      }\n\n      const stream  = new TransformStream()\n      const writer  = stream.writable.getWriter()\n      const reader  = new StreamReader( response.body )\n      const input   = new Transform()\n      \n      reader.read()\n      \n\n      reader.on( 'read', chunk =\u003e {\n        input.push( chunk )\n      } )\n      reader.on( 'close', () =\u003e {\n        input.push( null )\n      } )\n\n      const output = new Writable( {\n        write( chunk, encoding, callback )\n        {\n          writer.write( chunk )\n          callback()\n        },\n        final( callback ) {\n          writer.close()\n          callback()\n        },\n      } )\n      \n      const { decrypt } = await Cipher.streamDecrypt( password, { input, output } )\n\n      decrypt()\n      \n      return (\n        // decrypted stream\n        new Response( stream.readable )\n      )\n      \n    } )\n)\n```\n\n---\n\n#### In-memory data stream with hybrid encryption/decryption\n\nHybrid encryption offers an higher level of security by encrypting the generated symmetric key with asymmetric RSA keys.\n\n##### Keypair\n\n```ts\nconst password  = 'my-very-strong-password'\n\n/** RSA modulus length is required for proper key extraction during decryption process. */\nconst rsaKeyLength = 512 // bytes\nconst keyPair = crypto.generateKeyPairSync( 'rsa', {\n  modulusLength       : rsaKeyLength * 8, // 4096 bits\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs1', format: 'pem' },\n} )\n\n\n// or you can optionally set a custom passphrase\nconst keyPair = crypto.generateKeyPairSync( 'rsa', {\n  modulusLength       : rsaKeyLength * 8, // 4096 bits\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs1', format: 'pem', passphrase: password, cipher: 'aes-256-cbc' },\n} )\n```\n\n##### Encrypt\n\n```ts\nconst data = 'my top-secret data'\n/** Store encrypted chunks for next example. */\nconst encryptedChunks: Buffer[] = []\n\n// Create a `Readable` Stream with raw data.\nconst input = new Readable( {\n  read()\n  {\n    this.push( data ) // Push data to encrypt\n    this.push( null ) // Signal end of stream\n  },\n} )\n    \n// Create a `Writable` Stream where encrypted data is written\nconst output = new Writable( {\n  write( chunk, encoding, callback )\n  {\n    // push written chunk to `encryptedChunks` for further usage.\n    encryptedChunks.push( chunk )\n    callback()\n  }\n} )\n\nconst { encrypt } = Cipher.hybridEncrypt( password, {\n  key       : keyPair.publicKey,\n  padding   : crypto.constants.RSA_PKCS1_OAEP_PADDING,\n  oaepHash  : 'SHA-256',\n}, { input, output } )\n\nawait encrypt()\n```\n\n---\n\n##### Decrypt\n\n```ts\n/** Store decrypted chunks. */\nconst chunks: Buffer[] = []\n// Create a `Readable` Stream with encrypted data.\nconst input = new Readable( {\n  read()\n  {\n    this.push( Buffer.concat( encryptedChunks ) ) // Push data to decrypt\n    this.push( null ) // Signal end of stream\n  },\n} )\n\n// Create a `Writable` Stream where decrypted data is written\nconst output = new Writable( {\n  write( chunk, encoding, callback )\n  {\n    chunks.push( chunk )\n    callback()\n  },\n} )\n\nconst { decrypt } = await Cipher.hybridDecrypt(\n  {\n    key       : keyPair.privateKey,\n    passphrase: password, // optional passhrase (required if set while generating keypair).\n    padding   : crypto.constants.RSA_PKCS1_OAEP_PADDING,\n    oaepHash  : 'SHA-256',\n  }, { input, output, rsaKeyLength }\n)\n\nawait decrypt()\n\nconsole.log( Buffer.concat( chunks ).toString() ) // Outputs: 'my top-secret data'\n```\n\n---\n\n#### File based data stream encryption/decryption\n\nNothig differs from the [In-memory data stream encryption/decryption](#in-memory-data-stream-encryptiondecryption) example, except for `input` and `output` streams which now comes directly from files reading/writing.\n\n##### Encrypt a file\n\n```ts\nimport fs from 'fs'\n\nconst password = 'my-very-strong-password'\n\n// input where raw data to encrypt is read\nconst input = fs.createReadStream( 'my-very-large-top-secret-file.pdf' )\n// output where encrypted data is written\nconst output = fs.createWriteStream( 'my-very-large-top-secret-file.encrypted' )\n// encrypt\nawait Cipher.streamEncrypt( password, { input, output } )\n  .encrypt()\n```\n\n---\n\n##### Decrypt a file\n\n```ts\nimport fs from 'fs'\n\nconst password = 'my-very-strong-password'\n\n// input where encrypted data is read\nconst input = fs.createReadStream( 'my-very-large-top-secret-file.encrypted' )\n// output where decrypted data is written\nconst output = fs.createWriteStream( 'my-very-large-top-secret-file-decrypted.pdf' )\n// decrypt\nconst { decrypt } = await Cipher.streamDecrypt( password, { input, output } )\nawait decrypt()\n```\n\n---\n\n#### File based data stream with hybrid encryption/decryption\n\nNothig differs from the [In-memory data stream with hybrid encryption/decryption](#in-memory-data-stream-with-hybrid-encryptiondecryption) example, except for `input` and `output` streams which now comes directly from files reading/writing.\n\n##### Keypair\n\n```ts\nconst password  = 'my-very-strong-password'\n\n/** RSA modulus length is required for proper key extraction during decryption process. */\nconst rsaKeyLength = 512 // bytes\nconst keyPair = crypto.generateKeyPairSync( 'rsa', {\n  modulusLength       : rsaKeyLength * 8, // 4096 bits\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs1', format: 'pem' },\n} )\n\n\n// or you can optionally set a custom passphrase\nconst keyPair = crypto.generateKeyPairSync( 'rsa', {\n  modulusLength       : rsaKeyLength * 8, // 4096 bits\n  publicKeyEncoding   : { type: 'spki', format: 'pem' },\n  privateKeyEncoding  : { type: 'pkcs1', format: 'pem', passphrase: password, cipher: 'aes-256-cbc' },\n} )\n```\n\n##### Encrypt a file\n\n```ts\nimport fs from 'fs'\n\nconst password = 'my-very-strong-password'\n\n// input where raw data to encrypt is read\nconst input = fs.createReadStream( 'my-very-large-top-secret-file.pdf' )\n// output where encrypted data is written\nconst output = fs.createWriteStream( 'my-very-large-top-secret-file.encrypted' )\n// encrypt\nconst { encrypt } = Cipher.hybridEncrypt( password, {\n  key       : keyPair.publicKey,\n  padding   : crypto.constants.RSA_PKCS1_OAEP_PADDING,\n  oaepHash  : 'SHA-256',\n}, { input, output } )\nawait encrypt()\n```\n\n---\n\n##### Decrypt a file\n\n```ts\nimport fs from 'fs'\n\nconst password = 'my-very-strong-password'\n\n// input where encrypted data is read\nconst input = fs.createReadStream( 'my-very-large-top-secret-file.encrypted' )\n// output where decrypted data is written\nconst output = fs.createWriteStream( 'my-very-large-top-secret-file-decrypted.pdf' )\n// decrypt\nconst { decrypt } = await Cipher.hybridDecrypt(\n  {\n    key       : keyPair.privateKey,\n    passphrase: password, // optional passhrase (required if set while generating keypair).\n    padding   : crypto.constants.RSA_PKCS1_OAEP_PADDING,\n    oaepHash  : 'SHA-256',\n  }, { input, output, rsaKeyLength }\n)\n```\n\n---\n\n### Development\n\n#### Install depenendencies\n\n```bash\nnpm install\n```\n\nor using `pnpm`\n\n```bash\npnpm i\n```\n\n#### Build the source code\n\nRun the following command to test and build code for distribution.\n\n```bash\npnpm build\n```\n\n#### [ESLint](https://www.npmjs.com/package/eslint)\n\nwarnings / errors check.\n\n```bash\npnpm lint\n```\n\n#### [Jest](https://npmjs.com/package/jest)\n\nRun all the defined test suites by running the following:\n\n```bash\n# Run tests and watch file changes.\npnpm test:watch\n\n# Run tests in a CI environment.\npnpm test:ci\n```\n\n- See [`package.json`](./package.json) file scripts for more info.\n\nRun tests with coverage.\n\nAn HTTP server is then started to serve coverage files from `./coverage` folder.\n\n⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.\n\n```bash\ntest:coverage:serve\n```\n\n---\n\n### Contributing\n\nContributions are truly welcome!\n\nPlease refer to the [Contributing Doc](./CONTRIBUTING.md) for more information on how to start contributing to this project.\n\nHelp keep this project up to date with [GitHub Sponsor][sponsor-url].\n\n[![GitHub Sponsor][sponsor-badge]][sponsor-url]\n\n---\n\n### Security\n\nIf you believe you have found a security vulnerability, we encourage you to **_responsibly disclose this and NOT open a public issue_**. We will investigate all legitimate reports. Email `security@alessiofrittoli.it` to disclose any security vulnerabilities.\n\n### Made with ☕\n\n\u003ctable style='display:flex;gap:20px;'\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"avatar\" src='https://avatars.githubusercontent.com/u/35973186' style='width:60px;border-radius:50%;object-fit:contain;'\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003ctable style='display:flex;gap:2px;flex-direction:column;'\u003e\n          \u003ctbody\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003ca href='https://github.com/alessiofrittoli' target='_blank' rel='noopener'\u003eAlessio Frittoli\u003c/a\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n              \u003ctr\u003e\n                \u003ctd\u003e\n                  \u003csmall\u003e\n                    \u003ca href='https://alessiofrittoli.it' target='_blank' rel='noopener'\u003ehttps://alessiofrittoli.it\u003c/a\u003e |\n                    \u003ca href='mailto:info@alessiofrittoli.it' target='_blank' rel='noopener'\u003einfo@alessiofrittoli.it\u003c/a\u003e\n                  \u003c/small\u003e\n                \u003c/td\u003e\n              \u003c/tr\u003e\n          \u003c/tbody\u003e\n        \u003c/table\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fcrypto-cipher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falessiofrittoli%2Fcrypto-cipher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falessiofrittoli%2Fcrypto-cipher/lists"}