From 5a2a8b4c8ecb4b91b3876d31f6260159f5f9f80f Mon Sep 17 00:00:00 2001 From: s2224834 <46319860+s2224834@users.noreply.github.com> Date: Fri, 8 Feb 2019 18:08:13 +0000 Subject: [PATCH] Typex: input wiring is reversed --- src/core/lib/Typex.mjs | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/core/lib/Typex.mjs b/src/core/lib/Typex.mjs index b4cf297c..484a1e6b 100644 --- a/src/core/lib/Typex.mjs +++ b/src/core/lib/Typex.mjs @@ -2,6 +2,7 @@ * Emulation of the Typex machine. * * @author s2224834 + * @author The National Museum of Computing - Bombe Rebuild Project * @copyright Crown Copyright 2019 * @license Apache-2.0 */ @@ -28,7 +29,7 @@ export const ROTORS = [ * An example Typex reflector. Again, randomised. */ export const REFLECTORS = [ - {name: "Standard", value: "AN BC FG IE KD LU MH OR TS VZ WQ XJ YP"}, + {name: "Example", value: "AN BC FG IE KD LU MH OR TS VZ WQ XJ YP"}, ]; // Special character handling on Typex keyboard @@ -172,6 +173,8 @@ export class Rotor extends Enigma.Rotor { * Typex input plugboard. Based on a Rotor, because it allows arbitrary maps, not just switches * like the Enigma plugboard. * Not to be confused with the reflector plugboard. + * This is also where the Typex's backwards input wiring is implemented - it's a bit of a hack, but + * it means everything else continues to work like in the Enigma. */ export class Plugboard extends Enigma.Rotor { /** @@ -180,10 +183,45 @@ export class Plugboard extends Enigma.Rotor { * @param {string} wiring - 26 character string of mappings from A-Z, as per rotors, or "". */ constructor(wiring) { + // Typex input wiring is backwards vs Enigma: that is, letters enter the rotors in a + // clockwise order, vs. Enigma's anticlockwise (or vice versa depending on which side + // you're looking at it from). I'm doing the transform here to avoid having to rewrite + // the Engima crypt() method in Typex as well. + // Note that the wiring for the reflector is the same way around as Enigma, so no + // transformation is necessary on that side. + // We're going to achieve this by mapping the plugboard settings through an additional + // transform that mirrors the alphabet before we pass it to the superclass. + if (!/^[A-Z]{26}$/.test(wiring)) { + throw new OperationError("Plugboard wiring must be 26 unique uppercase letters"); + } + const reversed = "AZYXWVUTSRQPONMLKJIHGFEDCB"; + wiring = wiring.replace(/./g, x => { + return reversed[Enigma.a2i(x)]; + }); try { super(wiring, "", "A", "A"); } catch (err) { throw new OperationError(err.message.replace("Rotor", "Plugboard")); } } + + /** + * Transform a character through this rotor forwards. + * + * @param {number} c - The character. + * @returns {number} + */ + transform(c) { + return Utils.mod(this.map[Utils.mod(c + this.pos, 26)] - this.pos, 26); + } + + /** + * Transform a character through this rotor backwards. + * + * @param {number} c - The character. + * @returns {number} + */ + revTransform(c) { + return Utils.mod(this.revMap[Utils.mod(c + this.pos, 26)] - this.pos, 26); + } }