shielded-high-encryption
Version:
A secure encryption system using AES, named Shielded High Encryption (SHE)
488 lines (453 loc) • 18 kB
text/typescript
import { Encryption } from './index';
import { ShamirSecretSharing } from "./index";
import { KeyManagementSystemHandler } from './index';
import { FileSharder } from './index';
import * as readline from 'readline';
import fs from 'fs';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
const sss = new ShamirSecretSharing();
const argv = yargs(hideBin(process.argv))
.option('encrypt', {
alias: 'e',
type: 'string',
description: 'Text or file to encrypt'
})
.option('decrypt', {
alias: 'd',
type: 'string',
description: 'File to decrypt'
})
.option('file', {
alias: 'f',
type: 'boolean',
description: 'Specify if the input is a file'
})
.option('keyfolder', {
alias: 'k',
type: 'string',
description: 'Folder to save the encrypted key'
})
.option('dataefile', {
alias: 'ef',
type: 'string',
description: 'File to save the encrypted data'
})
.option('datadfile', {
alias: 'df',
type: 'string',
description: 'File to save the decrypted data'
})
.option('algorithm', {
alias: 'a',
type: 'string',
description: 'Encryption algorithm to use (aes-128-cbc, rsa)'
})
.option('mode', {
alias: 'm',
type: 'string',
description: 'Mode of operation to use (ecb, cbc, cfb, ofb, gcm)',
choices: ['ecb', 'cbc', 'cfb', 'ofb', 'gcm'],
default: 'cbc'
})
.option('keysize', {
alias: 'ks',
type: 'number',
description: 'Key size to use (128)',
choices: [128],
default: 128
})
.option('rotatekey', {
alias: 'r',
type: 'boolean',
description: 'Rotate the encryption key'
})
.option('hybridEncrypt', {
alias: 'he',
type: 'string',
description: 'Text to hybrid encrypt with public key'
})
.option('hybridDecrypt', {
alias: 'hd',
type: 'string',
description: 'Text to hybrid decrypt with private key'
})
.option('sign', {
alias: 's',
type: 'string',
description: 'Text to sign with private key'
})
.option('verify', {
alias: 'v',
type: 'string',
description: 'Text to verify signature with public key'
})
.option('generateDhKeys', {
alias: 'gk',
type: 'boolean',
description: 'Generate Diffie-Hellman keys'
})
.option('computeSecret', {
alias: 'cs',
type: 'string',
description: 'Compute shared secret with public key'
})
.option('generateOtp', {
alias: 'otp',
type: 'string',
description: 'Generate one-time password with a secret'
})
.option('validateOtp', {
alias: 'votp',
type: 'string',
description: 'Validate one-time password with a secret and otp'
})
.option('createBackup', {
alias: 'cb',
type: 'string',
description: 'Create encrypted backup of data'
})
.option('recoverBackup', {
alias: 'rb',
type: 'string',
description: 'Recover encrypted backup of data'
})
.option('addMetadata', {
alias: 'am',
type: 'string',
description: 'Add metadata to a file'
})
.option('getMetadata', {
alias: 'gm',
type: 'string',
description: 'Get metadata from a file'
})
.option('addKeyExpiration', {
alias: 'ake',
type: 'number',
description: 'Add expiration to a key in seconds'
})
.option('checkKeyExpiration', {
alias: 'cke',
type: 'boolean',
description: 'Check if the key has expired'
})
.option('encryptTwofish', {
alias: 'etf',
type: 'string',
description: 'Text to encrypt with Twofish'
})
.option('decryptTwofish', {
alias: 'dtf',
type: 'string',
description: 'Text to decrypt with Twofish'
})
.option('encryptChaCha20', {
alias: 'ecc',
type: 'string',
description: 'Text to encrypt with ChaCha20'
})
.option('decryptChaCha20', {
alias: 'dcc',
type: 'string',
description: 'Text to decrypt with ChaCha20'
})
.option("generateShares", {
type: "boolean",
description: "Generate shares from a secret",
})
.option("reconstructSecret", {
type: "boolean",
description: "Reconstruct the secret from shares",
})
.help()
.argv;
// Create da instance
const she = new Encryption(argv.algorithm, argv.mode, argv.keysize, argv.dataefile, argv.datadfile);
if (argv.keyfolder) {
she.setKeyFolder(argv.keyfolder);
}
// Save that boi
const saveKey = (key: Buffer | string, filename: string) => {
she.saveKey(key, filename);
};
// Load that boi up
const loadKey = (filename: string): Buffer | string => {
return she.loadKey(filename);
};
// Encryption and Decryption :D
const main = async () => {
if (argv.rotatekey) {
await she.rotateKey();
console.log('Encryption key rotated');
} else if (argv.encrypt) {
try {
const salt = she.generateIv();
const key = she.deriveKeyFromPassword('', salt);
const iv = she.generateIv();
saveKey(key, 'key.bin');
saveKey(iv, 'iv.bin');
saveKey(salt, 'salt.bin');
let plaintext;
if (argv.file) {
plaintext = fs.readFileSync(argv.encrypt, 'utf8');
} else {
plaintext = argv.encrypt;
}
const encryptedText = she.encrypt(plaintext, key, iv);
console.log(`Encrypted Text: ${encryptedText}`);
} catch (error) {
console.error('An error occurred:', error);
}
} else if (argv.decrypt) {
try {
const encryptedText = fs.readFileSync(argv.decrypt, 'utf8');
const loadedIv = loadKey('iv.bin') as Buffer;
const loadedSalt = loadKey('salt.bin') as Buffer;
const derivedKey = she.deriveKeyFromPassword('', loadedSalt);
const decryptedText = she.decrypt(encryptedText, derivedKey, loadedIv);
console.log(`Decrypted Text: ${decryptedText}`);
} catch (error) {
console.error('An error occurred:', error);
}
} else if (argv.hybridEncrypt) {
try {
const publicKey = fs.readFileSync('publicKey.pem', 'utf8');
const hybridEncryptedText = she.hybridEncrypt(argv.hybridEncrypt, publicKey);
console.log(`Hybrid Encrypted Text: ${hybridEncryptedText}`);
} catch (error) {
console.error('An error occurred during hybrid encryption:', error);
}
} else if (argv.hybridDecrypt) {
try {
const privateKey = fs.readFileSync('privateKey.pem', 'utf8');
const hybridDecryptedText = she.hybridDecrypt(argv.hybridDecrypt, privateKey);
console.log(`Hybrid Decrypted Text: ${hybridDecryptedText}`);
} catch (error) {
console.error('An error occurred during hybrid decryption:', error);
}
} else if (argv.sign) {
try {
const privateKey = fs.readFileSync('privateKey.pem', 'utf8');
const signature = she.signData(argv.sign, privateKey);
console.log(`Signature: ${signature}`);
} catch (error) {
console.error('An error occurred during signing:', error);
}
} else if (argv.verify) {
try {
const publicKey = fs.readFileSync('publicKey.pem', 'utf8');
const isValid = she.verifySignature(argv.verify, argv._[1], publicKey);
console.log(`Signature is valid: ${isValid}`);
} catch (error) {
console.error('An error occurred during signature verification:', error);
}
} else if (argv.generateDhKeys) {
try {
const { publicKey, privateKey } = she.generateDhKeys();
console.log(`Diffie-Hellman Public Key: ${publicKey}`);
console.log(`Diffie-Hellman Private Key: ${privateKey}`);
} catch (error) {
console.error('An error occurred during Diffie-Hellman key generation:', error);
}
} else if (argv.computeSecret) {
try {
const privateKey = fs.readFileSync('dhPrivateKey.pem', 'utf8');
const secret = she.computeSecret(argv.computeSecret, privateKey);
console.log(`Computed Shared Secret: ${secret.toString('hex')}`);
} catch (error) {
console.error('An error occurred during computing the shared secret:', error);
}
} else if (argv.generateOtp) {
try {
const otp = she.generateOtp(argv.generateOtp);
console.log(`Generated OTP: ${otp}`);
} catch (error) {
console.error('An error occurred during OTP generation:', error);
}
} else if (argv.validateOtp) {
try {
const isValid = she.validateOtp(argv.validateOtp, argv._[1]);
console.log(`OTP is valid: ${isValid}`);
} catch (error) {
console.error('An error occurred during OTP validation:', error);
}
} else if (argv.createBackup) {
try {
const key = loadKey('backupKey.bin') as Buffer;
const iv = loadKey('backupIv.bin') as Buffer;
she.createEncryptedBackup(argv.createBackup, key, iv, 'backup.enc');
console.log('Encrypted backup created successfully.');
} catch (error) {
console.error('An error occurred during creating an encrypted backup:', error);
}
} else if (argv.recoverBackup) {
try {
const key = loadKey('backupKey.bin') as Buffer;
const iv = loadKey('backupIv.bin') as Buffer;
const recoveredData = she.recoverEncryptedBackup('backup.enc', key, iv);
console.log(`Recovered Data: ${recoveredData}`);
} catch (error) {
console.error('An error occurred during recovering the encrypted backup:', error);
}
} else if (argv.addMetadata) {
try {
const metadata = JSON.parse(argv._[1]);
she.addMetadata(argv.addMetadata, metadata);
console.log('Metadata added successfully.');
} catch (error) {
console.error('An error occurred during adding metadata:', error);
}
} else if (argv.getMetadata) {
try {
const metadata = she.getMetadata(argv.getMetadata);
console.log(`Metadata: ${JSON.stringify(metadata, null, 2)}`);
} catch (error) {
console.error('An error occurred during fetching metadata:', error);
}
} else if (argv.addKeyExpiration) {
try {
const key = loadKey('key.bin') as Buffer;
she.addKeyExpiration(key, argv.addKeyExpiration);
console.log('Key expiration added successfully.');
} catch (error) {
console.error('An error occurred during adding key expiration:', error);
}
} else if (argv.checkKeyExpiration) {
try {
const isExpired = she.checkKeyExpiration();
console.log(`Key has expired: ${isExpired}`);
} catch (error) {
console.error('An error occurred during checking key expiration:', error);
}
} else if (argv.encryptTwofish) {
try {
const key = she.generateKey();
const iv = she.generateIv();
const encryptedText = she.encryptTwofish(argv.encryptTwofish, key, iv);
saveKey(key, 'twofishKey.bin');
saveKey(iv, 'twofishIv.bin');
console.log(`Twofish Encrypted Text: ${encryptedText}`);
} catch (error) {
console.error('An error occurred during Twofish encryption:', error);
}
} else if (argv.decryptTwofish) {
try {
const key = loadKey('twofishKey.bin') as Buffer;
const iv = loadKey('twofishIv.bin') as Buffer;
const decryptedText = she.decryptTwofish(argv.decryptTwofish, key, iv);
console.log(`Twofish Decrypted Text: ${decryptedText}`);
} catch (error) {
console.error('An error occurred during Twofish decryption:', error);
}
} else if (argv.encryptChaCha20) {
try {
const key = she.generateKey();
const nonce = she.generateIv(); // ChaCha20
const encryptedText = she.encryptChaCha20(argv.encryptChaCha20, key, nonce);
saveKey(key, 'chaCha20Key.bin');
saveKey(nonce, 'chaCha20Nonce.bin');
console.log(`ChaCha20 Encrypted Text: ${encryptedText}`);
} catch (error) {
console.error('An error occurred during ChaCha20 encryption:', error);
}
} else if (argv.decryptChaCha20) {
try {
const key = loadKey('chaCha20Key.bin') as Buffer;
const nonce = loadKey('chaCha20Nonce.bin') as Buffer;
const decryptedText = she.decryptChaCha20(argv.decryptChaCha20, key, nonce);
console.log(`ChaCha20 Decrypted Text: ${decryptedText}`);
} catch (error) {
console.error('An error occurred during ChaCha20 decryption:', error);
}
} else {
console.log('Please specify an action: --encrypt, --decrypt, --hybridEncrypt, --hybridDecrypt, --sign, --verify, --generateDhKeys, --computeSecret, --generateOtp, --validateOtp, --createBackup, --recoverBackup, --addMetadata, --getMetadata, --addKeyExpiration, --checkKeyExpiration, --encryptTwofish, --decryptTwofish, --encryptChaCha20, or --decryptChaCha20');
}
};
const shamir = require('shamir');
// Generate shares
function generateShares(secret, numShares, threshold) {
try {
const shares = shamir.split(secret, numShares, threshold);
console.log(`Generated shares: ${shares}`);
return shares;
} catch (error) {
console.error('An error occurred during generating shares:', error);
}
}
// Reconstruct secret
function reconstructSecrets(shares) {
try {
const secret = shamir.combine(shares);
console.log(`Reconstructed secret: ${secret}`);
return secret;
} catch (error) {
console.error('An error occurred during reconstructing secret:', error);
}
}
const keyManager = new KeyManagementSystemHandler();
// Example usage
const secret = Buffer.from('mySecret');
const numShares = 5;
const threshold = 3;
try {
// Generate shares
const shares = shamir.split(secret, numShares, threshold);
console.log(`Generated shares: ${shares}`);
// Save shares in the key management system
shares.forEach((share, index) => {
const keyId = `share-${index + 1}`;
keyManager.saveKey(keyId, share);
});
// Retrieve shares from the key management system
const retrievedShares: Buffer[] = [];
for (let i = 1; i <= threshold; i++) {
const keyId = `share-${i}`;
retrievedShares.push(keyManager.getKey(keyId));
}
// Reconstruct the secret
const reconstructedSecret = shamir.combine(retrievedShares);
console.log(`Reconstructed secret: ${reconstructedSecret.toString()}`);
} catch (error) {
console.error('An error occurred:', error);
}
const prompt = async (question: string): Promise<string> => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
return new Promise((resolve) => rl.question(question, (answer) => {
rl.close();
resolve(answer);
}));
};
(async () => {
try {
const fileSharder = new FileSharder();
// Prompt user for input file
const inputFilePath = await prompt("Enter the path to the input file: ");
if (!fs.existsSync(inputFilePath)) {
throw new Error(`File not found: ${inputFilePath}`);
}
// Prompt user for directory to save shards
let outputDir = await prompt("Enter the directory to save shards (or leave blank for default './shardedFiles'): ");
outputDir = outputDir || './shardedFiles'; // Default directory
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir); // Automatically create the directory if it doesn't exist
console.log(`Created directory: ${outputDir}`);
}
// Prompt user for output file to save reassembled data
let reassembledFilePath = await prompt("Enter the path for the reassembled file (or leave blank for default 'reconstructedFile.txt'): ");
reassembledFilePath = reassembledFilePath || 'reconstructedFile.txt'; // Default file
// Step 1: Split and encrypt the file
console.log('Starting file sharding and encryption...');
fileSharder.shardAndEncrypt(inputFilePath, outputDir);
// Step 2: Reassemble and decrypt the file
console.log('Starting reassembly and decryption...');
fileSharder.reassembleAndDecrypt(outputDir, reassembledFilePath);
console.log(`File processing complete! Check shards in ${outputDir} and the reassembled file at ${reassembledFilePath}.`);
} catch (error) {
console.error('An error occurred:', error.message);
}
})();
main();