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.

142 lines (141 loc) 6.99 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const fs_1 = require("fs"); const AESGCMEncryption_1 = require("../encryption/AESGCMEncryption"); const ChaCha20Poly1305Encryption_1 = require("../encryption/ChaCha20Poly1305Encryption"); const EncryptionService_1 = require("../services/EncryptionService"); function createEncryption(algorithm = 'aes-gcm') { switch (algorithm.toLowerCase()) { case 'chacha20-poly1305': case 'chacha20': return [ new ChaCha20Poly1305Encryption_1.ChaCha20Poly1305Encryption(), (password, encoding) => new ChaCha20Poly1305Encryption_1.ChaCha20Poly1305EncryptionConfig(password, encoding) ]; case 'aes-gcm': case 'aes': default: return [ new AESGCMEncryption_1.AESGCMEncryption(), (password, encoding) => new AESGCMEncryption_1.AESGCMEncryptionConfig(password, encoding) ]; } } const program = new commander_1.Command(); program .name('easy-cipher-mate') .description('A CLI tool for file encryption/decryption') .version('1.0.0'); const encryptCommand = program .command('encrypt-file') .description('Encrypt a file') .requiredOption('-i, --input <path>', 'Input file path') .requiredOption('-o, --output <path>', 'Output file path') .requiredOption('-p, --password <string>', 'Encryption password') .option('-a, --algorithm <string>', 'Encryption algorithm (aes-gcm or chacha20-poly1305)', 'aes-gcm') .action(async (options) => { try { const [encryption, configFactory] = createEncryption(options.algorithm); const config = configFactory(options.password); const service = new EncryptionService_1.EncryptionService(encryption, config); const fileBuffer = (0, fs_1.readFileSync)(options.input); const result = await service.encryptFile(fileBuffer.buffer); (0, fs_1.writeFileSync)(options.output, Buffer.from(result.data)); console.log(`File encrypted successfully using ${options.algorithm}`); } catch (error) { console.error('Encryption failed:', error instanceof Error ? error.message : String(error)); process.exit(1); } }); const decryptCommand = program .command('decrypt-file') .description('Decrypt a file') .requiredOption('-i, --input <path>', 'Input file path') .requiredOption('-o, --output <path>', 'Output file path') .requiredOption('-p, --password <string>', 'Decryption password') .option('-a, --algorithm <string>', 'Decryption algorithm (aes-gcm or chacha20-poly1305)', 'aes-gcm') .action(async (options) => { try { const [encryption, configFactory] = createEncryption(options.algorithm); const config = configFactory(options.password); const service = new EncryptionService_1.EncryptionService(encryption, config); const encryptedData = (0, fs_1.readFileSync)(options.input); const decrypted = await service.decryptFile(encryptedData.buffer); (0, fs_1.writeFileSync)(options.output, Buffer.from(decrypted)); console.log(`File decrypted successfully using ${options.algorithm}`); } catch (error) { console.error('Decryption failed:', error instanceof Error ? error.message : String(error)); process.exit(1); } }); const encryptTextFileCommand = program .command('encrypt-text-file') .description('Encrypt a text file line by line') .requiredOption('-f, --file <path>', 'Text file path') .requiredOption('-p, --password <string>', 'Encryption password') .option('-a, --algorithm <string>', 'Encryption algorithm (aes-gcm or chacha20-poly1305)', 'aes-gcm') .option('-e, --encoding <string>', 'Text encoding (utf-8, ascii, utf16le, base64, hex, latin1, binary)', 'utf-8') .action(async (options) => { try { const [encryption, configFactory] = createEncryption(options.algorithm); const config = configFactory(options.password, options.encoding); const service = new EncryptionService_1.EncryptionService(encryption, config); const content = (0, fs_1.readFileSync)(options.file, '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, options.encoding); return Buffer.from(result.data).toString('base64'); })); (0, fs_1.writeFileSync)(options.file, encryptedLines.join('\n')); console.log(`File encrypted line by line successfully using ${options.algorithm} with ${options.encoding} encoding`); } catch (error) { console.error('Text file encryption failed:', error instanceof Error ? error.message : String(error)); process.exit(1); } }); const decryptTextFileCommand = program .command('decrypt-text-file') .description('Decrypt a text file line by line') .requiredOption('-f, --file <path>', 'Text file path') .requiredOption('-p, --password <string>', 'Decryption password') .option('-a, --algorithm <string>', 'Decryption algorithm (aes-gcm or chacha20-poly1305)', 'aes-gcm') .option('-e, --encoding <string>', 'Text encoding (utf-8, ascii, utf16le, base64, hex, latin1, binary)', 'utf-8') .action(async (options) => { try { const [encryption, configFactory] = createEncryption(options.algorithm); const config = configFactory(options.password, options.encoding); const service = new EncryptionService_1.EncryptionService(encryption, config); const content = (0, fs_1.readFileSync)(options.file, 'utf-8'); const lines = content.split(/\r?\n/); const decryptedLines = await Promise.all(lines.map(async (line, index) => { if (line.trim() === '') return line; try { const buffer = Buffer.from(line, 'base64'); return await service.decryptText(buffer, options.encoding); } catch (e) { // If this is the first error we encounter, it might be due to wrong password if (index === lines.findIndex(l => l.trim() !== '')) { throw new Error('Invalid password'); } // Otherwise, just return the original line return line; } })); (0, fs_1.writeFileSync)(options.file, decryptedLines.join('\n')); console.log(`File decrypted line by line successfully using ${options.algorithm} with ${options.encoding} encoding`); } catch (error) { console.error('Text file decryption failed:', error instanceof Error ? error.message : String(error)); process.exit(1); } }); program.parse(process.argv);