diff --git a/src/core/lib/Bombe.mjs b/src/core/lib/Bombe.mjs index 53766560..1e6c3d2d 100644 --- a/src/core/lib/Bombe.mjs +++ b/src/core/lib/Bombe.mjs @@ -191,9 +191,6 @@ export class BombeMachine { if (ciphertext.length < crib.length) { throw new OperationError("Crib overruns supplied ciphertext"); } - if (ciphertext.length > crib.length) { - throw new OperationError("Ciphertext is longer than crib"); - } if (crib.length < 2) { // This is the absolute bare minimum to be sane, and even then it's likely too short to // be useful @@ -204,7 +201,7 @@ export class BombeMachine { // A shorter crib is preferable to reduce this chance, of course throw new OperationError("Crib is too long"); } - for (let i=0; i ${i2a(j)}`; + stecker = [this.testRegister, j]; break; } } } else if (count === 1) { // This means our hypothesis for the steckering is correct. - stecker = `${i2a(this.testRegister)} <-> ${i2a(this.testInput[1])}`; + stecker = [this.testRegister, this.testInput[1]]; } else { // Unusual, probably indicative of a poor menu. I'm a little unclear on how // this was really handled, but we'll return it for the moment. - stecker = `? (wire count: ${count})`; + stecker = undefined; } - result.push([this.indicator.getPos(), stecker]); + const testDecrypt = this.tryDecrypt(stecker); + let steckerStr; + if (stecker !== undefined) { + steckerStr = `${i2a(stecker[0])}${i2a(stecker[1])}`; + } else { + steckerStr = `?? (wire count: ${count})`; + } + result.push([this.indicator.getPos(), steckerStr, testDecrypt]); } // Step all the scramblers // This loop counts how many rotors have reached their starting position (meaning the diff --git a/src/core/operations/Bombe.mjs b/src/core/operations/Bombe.mjs index e875e50d..9ddd4b7b 100644 --- a/src/core/operations/Bombe.mjs +++ b/src/core/operations/Bombe.mjs @@ -112,7 +112,7 @@ class Bombe extends Operation { // For symmetry with the Enigma op, for the input we'll just remove all invalid characters input = input.replace(/[^A-Za-z]/g, "").toUpperCase(); crib = crib.replace(/[^A-Za-z]/g, "").toUpperCase(); - const ciphertext = input.slice(offset, offset+crib.length); + const ciphertext = input.slice(offset); const reflector = new Reflector(reflectorstr); let update; if (ENVIRONMENT_IS_WORKER()) { @@ -122,9 +122,9 @@ class Bombe extends Operation { } const bombe = new BombeMachine(rotors, reflector, ciphertext, crib, update); const result = bombe.run(); - let msg = `Bombe run on menu with ${bombe.nLoops} loops (2+ desirable). Note: Rotor positions are listed left to right and start at the beginning of the crib, and ignore stepping and the ring setting. One stecker pair is determined. Results:\n`; - for (const [setting, wires] of result) { - msg += `Stop: ${setting} (${wires})\n`; + let msg = `Bombe run on menu with ${bombe.nLoops} loops (2+ desirable). Note: Rotor positions are listed left to right and start at the beginning of the crib, and ignore stepping and the ring setting. One stecker pair is determined. A decryption preview starting at the beginning of the crib and ignoring stepping is also provided. Results:\n`; + for (const [setting, stecker, decrypt] of result) { + msg += `Stop: ${setting} (plugboard: ${stecker}): ${decrypt}\n`; } return msg; } diff --git a/tests/operations/tests/Bombe.mjs b/tests/operations/tests/Bombe.mjs index 8742cfc0..65f4b701 100644 --- a/tests/operations/tests/Bombe.mjs +++ b/tests/operations/tests/Bombe.mjs @@ -8,9 +8,10 @@ import TestRegister from "../TestRegister"; TestRegister.addTests([ { + // Plugboard for this test is BO LC KE GA name: "Bombe: 3 rotor (self-stecker)", input: "BBYFLTHHYIJQAYBBYS", - expectedMatch: /LGA \(S <-> S\)/, + expectedMatch: /LGA \(plugboard: SS\): VFISUSGTKSTMPSUNAK/, recipeConfig: [ { "op": "Bombe", @@ -28,7 +29,7 @@ TestRegister.addTests([ { name: "Bombe: 3 rotor (other stecker)", input: "JBYALIHDYNUAAVKBYM", - expectedMatch: /LGA \(A <-> G\)/, + expectedMatch: /LGA \(plugboard: AG\): QFIMUMAFKMQSKMYNGW/, recipeConfig: [ { "op": "Bombe", @@ -46,7 +47,7 @@ TestRegister.addTests([ { name: "Bombe: crib offset", input: "AAABBYFLTHHYIJQAYBBYS", // first three chars here are faked - expectedMatch: /LGA \(S <-> S\)/, + expectedMatch: /LGA \(plugboard: SS\): VFISUSGTKSTMPSUNAK/, recipeConfig: [ { "op": "Bombe", @@ -61,12 +62,30 @@ TestRegister.addTests([ } ] }, + { + name: "Bombe: multiple stops", + input: "BBYFLTHHYIJQAYBBYS", + expectedMatch: /LGA \(plugboard: TT\): VFISUSGTKSTMPSUNAK/, + recipeConfig: [ + { + "op": "Bombe", + "args": [ + "BDFHJLCPRTXVZNYEIWGAKMUSQO S\)/, + expectedMatch: /LHSC \(plugboard: SS\)/, recipeConfig: [ { "op": "Bombe",