UNPKG

easy-cipher-mate

Version:

A CLI and programmatic tool for encryption/decryption supporting AES-GCM and ChaCha20-Poly1305 algorithms, with text encoding options and line-by-line text file processing.

339 lines (254 loc) β€’ 11.8 kB
# easy-cipher-mate A secure, easy-to-use encryption library and CLI tool for Node.js and browser environments with built-in cryptographic best practices. ## πŸ”’ Security Features - **Automatic random salt generation** for each encryption operation - **Automatic random IV/nonce generation** for each encryption operation - **No IV/nonce reuse** - each encryption produces unique ciphertext even for identical plaintext - **PBKDF2 key derivation** with 100,000 iterations - **Authenticated encryption** with AES-GCM and ChaCha20-Poly1305 - **Secure data format** that packages salt, IV, and ciphertext together ## πŸš€ Features - Multiple encryption algorithms: - **AES-GCM** for robust symmetric encryption - **ChaCha20-Poly1305** for high-performance encryption - **Text encoding options** for multi-language support - **File encryption** capabilities - **Line-by-line text file** encryption - **Simple API** with security built-in - **CLI tool** for command-line usage ## πŸ“¦ Installation ### With npm ```bash npm install easy-cipher-mate ``` ### With yarn ```bash yarn add easy-cipher-mate ``` ## πŸ–₯️ CLI Usage ### Encrypt a file ```bash easy-cipher-mate encrypt-file -i input.txt -o output.txt -p yourpassword -a aes-gcm ``` ### Decrypt a file ```bash easy-cipher-mate decrypt-file -i encrypted.txt -o decrypted.txt -p yourpassword -a aes-gcm ``` ### Encrypt a text file line by line ```bash easy-cipher-mate encrypt-text-file -f input.txt -p yourpassword -a aes-gcm -e utf-8 ``` ### Decrypt a text file line by line ```bash easy-cipher-mate decrypt-text-file -f encrypted.txt -p yourpassword -a aes-gcm -e utf-8 ``` **Options:** - `-i, --input <path>`: Input file path (required) - `-o, --output <path>`: Output file path (required) - `-f, --file <path>`: Text file path (required) - `-p, --password <string>`: Encryption/decryption password (required) - `-a, --algorithm <string>`: Algorithm - 'aes-gcm' (default) or 'chacha20-poly1305' - `-e, --encoding <string>`: Text encoding - 'utf-8' (default), 'ascii', 'utf16le', 'base64', 'hex', 'latin1', or 'binary' ## πŸ’» Programmatic Usage ### Basic Text Encryption ```typescript import { AESGCMEncryption, AESGCMEncryptionConfig, EncryptionService } from 'easy-cipher-mate'; // Create encryption instance and configuration const encryption = new AESGCMEncryption(); const config = new AESGCMEncryptionConfig('your-secure-password'); const service = new EncryptionService(encryption, config); // Encrypt text const plaintext = 'Hello, World!'; const encrypted = await service.encryptText(plaintext); // Decrypt text const decrypted = await service.decryptText(encrypted.data); console.log(decrypted); // 'Hello, World!' // πŸ”’ Security: Each encryption produces different ciphertext! const encrypted1 = await service.encryptText(plaintext); const encrypted2 = await service.encryptText(plaintext); console.log(encrypted1.data !== encrypted2.data); // true - different ciphertext! ``` ### ChaCha20-Poly1305 Encryption ```typescript import { ChaCha20Poly1305Encryption, ChaCha20Poly1305EncryptionConfig, EncryptionService } from 'easy-cipher-mate'; const encryption = new ChaCha20Poly1305Encryption(); const config = new ChaCha20Poly1305EncryptionConfig('your-secure-password'); const service = new EncryptionService(encryption, config); const encrypted = await service.encryptText('Secret message'); const decrypted = await service.decryptText(encrypted.data); ``` ### Working with Different Text Encodings ```typescript import { AESGCMEncryption, AESGCMEncryptionConfig } from 'easy-cipher-mate'; const encryption = new AESGCMEncryption(); // Configure with specific text encoding const config = new AESGCMEncryptionConfig('my-password', 'base64'); // Encrypt text with base64 encoding const encrypted = await encryption.encryptText('Secret message', config); const decrypted = await encryption.decryptText(encrypted.data, config); // Override encoding for specific operations const hexEncrypted = await encryption.encryptText('Another message', config, 'hex'); const hexDecrypted = await encryption.decryptText(hexEncrypted.data, config, 'hex'); ``` ### Multi-language Support ```typescript import { AESGCMEncryption, AESGCMEncryptionConfig } from 'easy-cipher-mate'; const encryption = new AESGCMEncryption(); const config = new AESGCMEncryptionConfig('my-password'); // Encrypt Chinese text const chineseText = 'δ½ ε₯½οΌŒδΈ–η•Œ'; const encryptedChinese = await encryption.encryptText(chineseText, config); const decryptedChinese = await encryption.decryptText(encryptedChinese.data, config); // Encrypt Japanese text with UTF-16LE encoding const japaneseText = 'γ“γ‚“γ«γ‘γ―δΈ–η•Œ'; const encryptedJapanese = await encryption.encryptText(japaneseText, config, 'utf16le'); const decryptedJapanese = await encryption.decryptText(encryptedJapanese.data, config, 'utf16le'); // Encrypt emoji and mixed content const emojiText = 'πŸ‘‹ Hello! 🌍 δ½ ε₯½ こんにけは'; const encryptedEmoji = await encryption.encryptText(emojiText, config); const decryptedEmoji = await encryption.decryptText(encryptedEmoji.data, config); ``` ### File Encryption ```typescript import { AESGCMEncryption, AESGCMEncryptionConfig, EncryptionService } from 'easy-cipher-mate'; import { readFileSync, writeFileSync } from 'fs'; const encryption = new AESGCMEncryption(); const config = new AESGCMEncryptionConfig('my-password'); const service = new EncryptionService(encryption, config); // Encrypt a file const fileBuffer = readFileSync('document.pdf'); const arrayBuffer = fileBuffer.buffer.slice(fileBuffer.byteOffset, fileBuffer.byteOffset + fileBuffer.byteLength); const encryptedResult = await encryption.encryptFile(arrayBuffer, config); writeFileSync('document.pdf.encrypted', Buffer.from(encryptedResult.data)); // Decrypt the file const encryptedFileBuffer = readFileSync('document.pdf.encrypted'); const encryptedArrayBuffer = encryptedFileBuffer.buffer.slice( encryptedFileBuffer.byteOffset, encryptedFileBuffer.byteOffset + encryptedFileBuffer.byteLength ); const decryptedBuffer = await encryption.decryptFile(encryptedArrayBuffer, config); writeFileSync('document.pdf.decrypted', Buffer.from(decryptedBuffer)); // Simplified file operations with EncryptionService const encrypted = await service.encryptFileByName('document.pdf'); await service.decryptFileByName(encrypted, 'document.pdf.decrypted'); ``` ### Line-by-Line Text File Encryption ```typescript import { AESGCMEncryption, AESGCMEncryptionConfig, EncryptionService } from 'easy-cipher-mate'; import { readFileSync, writeFileSync } from 'fs'; const encryption = new AESGCMEncryption(); const config = new AESGCMEncryptionConfig('my-password'); const service = new EncryptionService(encryption, config); // Read and encrypt each line const content = readFileSync('document.txt', 'utf-8'); const lines = content.split(/\r?\n/); const encryptedLines = await Promise.all( lines.map(async line => { if (line.trim() === '') return line; const result = await service.encryptText(line); return Buffer.from(result.data).toString('base64'); }) ); writeFileSync('document.txt.encrypted', encryptedLines.join('\n')); // Decrypt each line const encryptedContent = readFileSync('document.txt.encrypted', 'utf-8'); const encryptedLinesArray = encryptedContent.split(/\r?\n/); const decryptedLines = await Promise.all( encryptedLinesArray.map(async line => { if (line.trim() === '') return line; const buffer = Buffer.from(line, 'base64'); return await service.decryptText(buffer); }) ); writeFileSync('document.txt.decrypted', decryptedLines.join('\n')); ``` ## πŸ”§ API Reference ### Encryption Algorithms #### AESGCMEncryption ```typescript class AESGCMEncryption { encryptText(plaintext: string, config: IAESGCMEncryptionConfig, encoding?: TextEncoding): Promise<EncryptionResult> decryptText(encryptedData: ArrayBuffer, config: IAESGCMEncryptionConfig, encoding?: TextEncoding): Promise<string> encryptFile(fileBuffer: ArrayBuffer, config: IAESGCMEncryptionConfig): Promise<EncryptionResult> decryptFile(encryptedBuffer: ArrayBuffer, config: IAESGCMEncryptionConfig): Promise<ArrayBuffer> } ``` #### ChaCha20Poly1305Encryption ```typescript class ChaCha20Poly1305Encryption { encryptText(plaintext: string, config: IChaCha20Poly1305EncryptionConfig, encoding?: TextEncoding): Promise<EncryptionResult> decryptText(encryptedData: ArrayBuffer, config: IChaCha20Poly1305EncryptionConfig, encoding?: TextEncoding): Promise<string> encryptFile(fileBuffer: ArrayBuffer, config: IChaCha20Poly1305EncryptionConfig): Promise<EncryptionResult> decryptFile(encryptedBuffer: ArrayBuffer, config: IChaCha20Poly1305EncryptionConfig): Promise<ArrayBuffer> } ``` ### Configuration Classes #### AESGCMEncryptionConfig ```typescript class AESGCMEncryptionConfig { constructor(password: string, textEncoding?: TextEncoding) } ``` #### ChaCha20Poly1305EncryptionConfig ```typescript class ChaCha20Poly1305EncryptionConfig { constructor(password: string, textEncoding?: TextEncoding) } ``` ### EncryptionService A wrapper class that simplifies encryption operations: ```typescript class EncryptionService<TAlgorithm, TConfig> { encryptText(plaintext: string, encoding?: TextEncoding): Promise<EncryptionResult> decryptText(encryptedData: ArrayBuffer, encoding?: TextEncoding): Promise<string> encryptFile(fileBuffer: ArrayBuffer, encoding?: TextEncoding): Promise<EncryptionResult> decryptFile(encryptedBuffer: ArrayBuffer, encoding?: TextEncoding): Promise<ArrayBuffer> encryptFileByName(fileName: string): Promise<EncryptionResult> decryptFileByName(encryptedResult: EncryptionResult, fileName: string): Promise<void> } ``` ## πŸ“ Supported Text Encodings - `utf-8` (default): Unicode encoding, supports all languages - `ascii`: ASCII encoding (7-bit, basic English characters only) - `utf16le`: UTF-16 Little Endian encoding - `base64`: Base64 encoding - `hex`: Hexadecimal encoding - `latin1`/`binary`: Latin-1 encoding (single byte per character) ## πŸ”’ Security Best Practices This library implements cryptographic best practices automatically: 1. **Random Salt Generation**: Each encryption generates a new random 16-byte salt 2. **Random IV/Nonce Generation**: Each encryption generates a new random IV (12 bytes for AES-GCM) or nonce (12 bytes for ChaCha20-Poly1305) 3. **No Key/IV Reuse**: The combination of key and IV/nonce is never reused 4. **Strong Key Derivation**: PBKDF2 with 100,000 iterations and SHA-256 5. **Authenticated Encryption**: Both algorithms provide built-in authentication 6. **Secure Data Format**: Salt, IV/nonce, and ciphertext are packaged together ### Data Format The encrypted output follows this format: - **AES-GCM**: `[16-byte salt][12-byte IV][ciphertext with auth tag]` - **ChaCha20-Poly1305**: `[16-byte salt][12-byte nonce][ciphertext][16-byte auth tag]` ## 🀝 Contributing Feel free to open issues or pull requests. For more information on how to contribute, please visit the [contribution guidelines](CONTRIBUTING.md). ## πŸ“„ License MIT License. See [LICENSE](LICENSE) for more details. --- ## 🚨 Migration from v1.x If you're upgrading from v1.x, note that the API has been simplified for better security: **Old (v1.x) - INSECURE:** ```typescript // ❌ Old way - manually setting salt/IV (security risk!) const config = new AESGCMEncryptionConfigFromEnv(password, salt, iv); ``` **New (v2.x) - SECURE:** ```typescript // βœ… New way - automatic random salt/IV generation const config = new AESGCMEncryptionConfig(password); ``` The new version automatically generates random salt and IV for each encryption, eliminating the security risks of the previous approach.