Bladeren bron

Typex: input wiring is reversed

s2224834 6 jaren geleden
bovenliggende
commit
5a2a8b4c8e
1 gewijzigde bestanden met toevoegingen van 39 en 1 verwijderingen
  1. 39 1
      src/core/lib/Typex.mjs

+ 39 - 1
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);
+    }
 }