crypto-keygen-suite
Version:
Key generation utilities for cryptographic operations. YES I RENAMED IT. SIX STATE PROTOCOL!!! See its folder for all <3
118 lines (104 loc) • 3.22 kB
JavaScript
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
function prepareKeyMatrix(key) {
key = key.toUpperCase().replace(/J/g, "I").replace(/[^A-Z]/g, "");
const seen = new Set();
const matrix = [];
for (const ch of key) {
if (!seen.has(ch)) {
matrix.push(ch);
seen.add(ch);
}
}
for (let i = 65; i <= 90; i++) {
const ch = String.fromCharCode(i);
if (ch === 'J') continue;
if (!seen.has(ch)) {
matrix.push(ch);
seen.add(ch);
}
}
const grid = [];
for (let i = 0; i < 25; i += 5) {
grid.push(matrix.slice(i, i + 5));
}
return grid;
}
function findPosition(grid, letter) {
for (let r = 0; r < 5; r++) {
for (let c = 0; c < 5; c++) {
if (grid[r][c] === letter) return [r, c];
}
}
return null;
}
function processText(text) {
text = text.toUpperCase().replace(/J/g, 'I').replace(/[^A-Z]/g, '');
const result = [];
for (let i = 0; i < text.length; i++) {
let a = text[i];
let b = text[i + 1] || 'X';
if (a === b) {
result.push(a);
result.push('X');
} else {
result.push(a);
if (i + 1 < text.length) {
result.push(b);
i++;
} else {
result.push('X');
}
}
}
return result;
}
function playfairCipher(text, grid, encrypt = true) {
const shift = encrypt ? 1 : -1;
const digrams = [];
for (let i = 0; i < text.length; i += 2) {
digrams.push([text[i], text[i + 1]]);
}
let output = '';
for (const [a, b] of digrams) {
const [r1, c1] = findPosition(grid, a);
const [r2, c2] = findPosition(grid, b);
if (r1 === r2) {
output += grid[r1][(c1 + shift + 5) % 5];
output += grid[r2][(c2 + shift + 5) % 5];
} else if (c1 === c2) {
output += grid[(r1 + shift + 5) % 5][c1];
output += grid[(r2 + shift + 5) % 5][c2];
} else {
output += grid[r1][c2];
output += grid[r2][c1];
}
}
return output;
}
const argv = yargs(hideBin(process.argv))
.usage('Usage: $0 <command> --key <key> --text <text>')
.command('encrypt', 'Encrypt text', y => y
.option('key', { type: 'string', demandOption: true, describe: 'Cipher key' })
.option('text', { type: 'string', demandOption: true, describe: 'Plaintext to encrypt' }))
.command('decrypt', 'Decrypt text', y => y
.option('key', { type: 'string', demandOption: true, describe: 'Cipher key' })
.option('text', { type: 'string', demandOption: true, describe: 'Ciphertext to decrypt' }))
.demandCommand(1, 'You need to specify a command: encrypt or decrypt')
.help()
.argv;
const command = argv._[0];
const key = argv.key;
const text = argv.text;
const matrix = prepareKeyMatrix(key);
const processedText = processText(text);
if (command === 'encrypt') {
const encrypted = playfairCipher(processedText, matrix, true);
console.log('Encrypted:', encrypted);
} else if (command === 'decrypt') {
const decrypted = playfairCipher(processedText, matrix, false);
console.log('Decrypted:', decrypted);
} else {
console.error('Unknown command:', command);
process.exit(1);
}