crypto-keygen-suite
Version:
Key generation utilities for cryptographic operations. YES I RENAMED IT. SIX STATE PROTOCOL!!! See its folder for all <3
180 lines (161 loc) • 5 kB
JavaScript
function charToNum(c) {
return c.toUpperCase().charCodeAt(0) - 65;
}
function numToChar(n) {
return String.fromCharCode((n % 26) + 65);
}
function padPlaintext(text) {
text = text.toUpperCase().replace(/[^A-Z]/g, '');
while (text.length % 3 !== 0) text += 'X';
return text;
}
function matrixMultiplyMod26(matrix, vector) {
let result = [];
for (let i = 0; i < 3; i++) {
let sum = 0;
for (let j = 0; j < 3; j++) {
sum += matrix[i][j] * vector[j];
}
result[i] = ((sum % 26) + 26) % 26;
}
return result;
}
function detMod26(m) {
const det =
m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) +
m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
return ((det % 26) + 26) % 26;
}
function modInverse(a, m = 26) {
let m0 = m, x0 = 0, x1 = 1;
if (m === 1) return 0;
while (a > 1) {
let q = Math.floor(a / m);
[a, m] = [m, a % m];
[x0, x1] = [x1 - q * x0, x0];
}
if (x1 < 0) x1 += m0;
return x1;
}
function matrixOfMinors(m) {
return [
[
(m[1][1] * m[2][2] - m[1][2] * m[2][1]) % 26,
(m[1][0] * m[2][2] - m[1][2] * m[2][0]) % 26,
(m[1][0] * m[2][1] - m[1][1] * m[2][0]) % 26,
],
[
(m[0][1] * m[2][2] - m[0][2] * m[2][1]) % 26,
(m[0][0] * m[2][2] - m[0][2] * m[2][0]) % 26,
(m[0][0] * m[2][1] - m[0][1] * m[2][0]) % 26,
],
[
(m[0][1] * m[1][2] - m[0][2] * m[1][1]) % 26,
(m[0][0] * m[1][2] - m[0][2] * m[1][0]) % 26,
(m[0][0] * m[1][1] - m[0][1] * m[1][0]) % 26,
],
];
}
function cofactorMatrix(m) {
const cof = matrixOfMinors(m);
for (let i = 0; i < 3; i++)
for (let j = 0; j < 3; j++) {
if ((i + j) % 2 === 1) cof[i][j] = -cof[i][j];
cof[i][j] = ((cof[i][j] % 26) + 26) % 26;
}
return cof;
}
function transposeMatrix(m) {
let t = [];
for (let i = 0; i < 3; i++) {
t[i] = [];
for (let j = 0; j < 3; j++) t[i][j] = m[j][i];
}
return t;
}
function scalarMultiplyMatrix(m, scalar) {
let r = [];
for (let i = 0; i < 3; i++) {
r[i] = [];
for (let j = 0; j < 3; j++) r[i][j] = (m[i][j] * scalar) % 26;
}
return r;
}
function matrixInverseMod26(m) {
const det = detMod26(m);
const detInv = modInverse(det);
if (detInv === 0) throw new Error("Matrix not invertible mod 26");
const cof = cofactorMatrix(m);
const adj = transposeMatrix(cof);
const inv = scalarMultiplyMatrix(adj, detInv);
for (let i = 0; i < 3; i++)
for (let j = 0; j < 3; j++)
inv[i][j] = ((inv[i][j] % 26) + 26) % 26;
return inv;
}
function hillEncrypt(text, keyMatrix) {
text = padPlaintext(text);
let ciphertext = "";
for (let i = 0; i < text.length; i += 3) {
const block = [charToNum(text[i]), charToNum(text[i+1]), charToNum(text[i+2])];
const encBlock = matrixMultiplyMod26(keyMatrix, block);
ciphertext += encBlock.map(numToChar).join('');
}
return ciphertext;
}
function hillDecrypt(text, keyMatrix) {
text = text.toUpperCase().replace(/[^A-Z]/g, '');
const invKey = matrixInverseMod26(keyMatrix);
let plaintext = "";
for (let i = 0; i < text.length; i += 3) {
const block = [charToNum(text[i]), charToNum(text[i+1]), charToNum(text[i+2])];
const decBlock = matrixMultiplyMod26(invKey, block);
plaintext += decBlock.map(numToChar).join('');
}
return plaintext;
}
function parseKeyMatrix(str) {
// str example: "6,24,1;13,16,10;20,17,15"
const rows = str.split(';');
if (rows.length !== 3) throw new Error("Key must be 3 rows");
const matrix = rows.map(row => {
const nums = row.split(',').map(Number);
if (nums.length !== 3 || nums.some(isNaN)) throw new Error("Each row must have 3 numbers");
return nums.map(n => ((n % 26) + 26) % 26);
});
return matrix;
}
// --- CLI Logic ---
const args = process.argv.slice(2);
if (args.length < 3) {
console.log("Usage:");
console.log(" node hillcipher.js encrypt <plaintext> <key>");
console.log(" node hillcipher.js decrypt <ciphertext> <key>");
console.log("Key format: 3 rows separated by semicolons, each row 3 comma-separated numbers");
console.log('Example key: "6,24,1;13,16,10;20,17,15"');
process.exit(1);
}
const [command, text, keyStr] = args;
let keyMatrix;
try {
keyMatrix = parseKeyMatrix(keyStr);
} catch (e) {
console.error("Invalid key:", e.message);
process.exit(1);
}
try {
if (command === "encrypt") {
const encrypted = hillEncrypt(text, keyMatrix);
console.log("Encrypted:", encrypted);
} else if (command === "decrypt") {
const decrypted = hillDecrypt(text, keyMatrix);
console.log("Decrypted:", decrypted);
} else {
console.error("Unknown command. Use encrypt or decrypt.");
process.exit(1);
}
} catch (e) {
console.error("Error:", e.message);
process.exit(1);
}