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
JavaScript
;
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);