UNPKG

crypto-keygen-suite

Version:

Key generation utilities for cryptographic operations. YES I RENAMED IT. SIX STATE PROTOCOL!!! See its folder for all <3

187 lines (154 loc) 5.55 kB
#!/usr/bin/env node import { program } from "commander"; const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Rotor wirings historical (right-to-left) const ROTORS = { I: "EKMFLGDQVZNTOWYHXUSPAIBRCJ", II: "AJDKSIRUXBLHWTMCQGZNPYFVOE", III: "BDFHJLCPRTXVZNYEIWGAKMUSQO", IV: "ESOVPZJAYQUIRHXLNFTGKDCMWB", V: "VZBRGITYUPSDNHLXAWMJQOFECK", VI: "JPGVOUMFYQBENHZRDKASXLICTW", VII: "NZJHGRCXMYSWBOUFAIVLPEKQDT", VIII: "FKQHTLXOCBJSPDZRAMEWNIUYGV", }; const REFLECTORS = { B: "YRUHQSLDPXNGOKMIEBFZCWVJAT", C: "FVPJIAOYEDRZXWGCTKUQSBNMHL", }; // Sanitize input: uppercase and keep letters only function sanitizeInput(input) { return input.toUpperCase().replace(/[^A-Z]/g, ""); } // Plugboard class: swaps pairs of letters class Plugboard { constructor(pairs) { this.mapping = {}; if (!pairs) return; for (const pair of pairs) { if (pair.length !== 2) continue; const [a, b] = pair.toUpperCase().split(""); this.mapping[a] = b; this.mapping[b] = a; } } swap(char) { return this.mapping[char] || char; } } // Rotor class class Rotor { constructor(wiring, positionChar = "A") { this.wiring = wiring; this.position = ALPHABET.indexOf(positionChar.toUpperCase()); this.ringSetting = 0; // For future: ring settings can be added } // Map input letter through rotor forward (right to left) forward(c) { const index = (ALPHABET.indexOf(c) + this.position - this.ringSetting + 26) % 26; const wiredChar = this.wiring[index]; const outputIndex = (ALPHABET.indexOf(wiredChar) - this.position + this.ringSetting + 26) % 26; return ALPHABET[outputIndex]; } // Map input letter through rotor backward (left to right) backward(c) { const index = (ALPHABET.indexOf(c) + this.position - this.ringSetting + 26) % 26; const wiredIndex = this.wiring.indexOf(ALPHABET[index]); const outputIndex = (wiredIndex - this.position + this.ringSetting + 26) % 26; return ALPHABET[outputIndex]; } // Rotate rotor by one position, returns true if at notch to step next rotor (simplified no notches) step() { this.position = (this.position + 1) % 26; return false; // Not implementing notch stepping here for simplicity } } // Reflector class class Reflector { constructor(wiring) { this.wiring = wiring; } reflect(c) { return this.wiring[ALPHABET.indexOf(c)]; } } // Enigma machine class class Enigma { constructor(rotorNames, rotorPositions, reflectorName, plugboardPairs) { if (rotorNames.length !== rotorPositions.length) { throw new Error("Rotor names and positions count mismatch"); } this.rotors = rotorNames.map((r, i) => new Rotor(ROTORS[r], rotorPositions[i])); this.reflector = new Reflector(REFLECTORS[reflectorName]); this.plugboard = new Plugboard(plugboardPairs); } stepRotors() { // Simple stepping: rightmost rotor always steps // Double stepping and notches not implemented for simplicity if (this.rotors.length === 0) return; this.rotors[0].step(); } processChar(c) { if (!ALPHABET.includes(c)) return c; // Preserve non-alpha if any this.stepRotors(); // Through plugboard in let ch = this.plugboard.swap(c); // Forward through rotors (right to left) for (const rotor of this.rotors) { ch = rotor.forward(ch); } // Reflect ch = this.reflector.reflect(ch); // Backward through rotors (left to right) for (let i = this.rotors.length - 1; i >= 0; i--) { ch = this.rotors[i].backward(ch); } // Through plugboard out ch = this.plugboard.swap(ch); return ch; } encrypt(text) { const sanitized = sanitizeInput(text); let result = ""; for (const c of sanitized) { result += this.processChar(c); } return result; } } // CLI setup with Commander.js program .argument('<mode>', 'encrypt or decrypt') .argument('<text>', 'text to encrypt/decrypt') .option('--rotors <rotors>', 'Comma-separated rotors (I-VIII)', 'I,II,III') .option('--positions <positions>', 'Comma-separated rotor start positions (A-Z)', 'A,A,A') .option('--reflector <reflector>', 'Reflector (B or C)', 'B') .option('--plugboard <pairs...>', 'Plugboard pairs e.g. AB CD EF'); program.parse(); const options = program.opts(); const mode = program.args[0].toLowerCase(); const inputText = program.args[1]; // Parse rotor names & positions const rotorNames = options.rotors.split(",").map(r => r.trim().toUpperCase()); const rotorPositions = options.positions.split(",").map(p => p.trim().toUpperCase()); // Validate reflector choice const reflectorName = options.reflector.toUpperCase(); if (!REFLECTORS[reflectorName]) { console.error(`Invalid reflector ${reflectorName}. Choose B or C.`); process.exit(1); } // Plugboard pairs (uppercase, max 10 pairs recommended) const plugboardPairs = options.plugboard || []; try { const enigma = new Enigma(rotorNames, rotorPositions, reflectorName, plugboardPairs); if (mode !== "encrypt" && mode !== "decrypt") { console.error("Mode must be either 'encrypt' or 'decrypt'"); process.exit(1); } // Enigma encryption/decryption are symmetric const output = enigma.encrypt(inputText); console.log("Result:", output); } catch (e) { console.error("Error:", e.message); process.exit(1); }