UNPKG

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