mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-23 08:16:17 -04:00
Bombe: review, tests, validation
This commit is contained in:
parent
b6eb4e84e4
commit
ad6e30f3d4
5 changed files with 173 additions and 31 deletions
|
@ -23,7 +23,7 @@ class Bombe extends Operation {
|
|||
|
||||
this.name = "Bombe";
|
||||
this.module = "Default";
|
||||
this.description = "";
|
||||
this.description = "Emulation of the Bombe machine used to attack Enigma.<br><br>To run this you need to have a 'crib', which is some known plaintext for a chunk of the target ciphertext, and know the rotors used. (See the 'Bombe (multiple runs)' operation if you don't know the rotors.) The machine will suggest possible configurations of the Enigma. Each suggestion has the rotor start positions (left to right) and one plugboard pair.<br><br>Choosing a crib: First, note that Enigma cannot encrypt a letter to itself, which allows you to rule out some positions for possible cribs. Secondly, the Bombe does not simulate the Enigma's middle rotor stepping. The longer your crib, the more likely a step happened within it, which will prevent the attack working. However, other than that, longer cribs are generally better. The attack produces a 'menu' which maps ciphertext letters to plaintext, and the goal is to produce 'loops': for example, with ciphertext ABC and crib CAB, we have the mappings A<->C, B<->A, and C<->B, which produces a loop A-B-C-A. The more loops, the better the crib. The operation will output this: if your menu has too few loops, a large number of incorrect outputs will be produced. Try a different crib. If the menu seems good but the right answer isn't produced, your crib may be wrong, or you may have overlapped the middle rotor stepping - try a different crib.<br><br>Output is not sufficient to fully decrypt the data. You will have to recover the rest of the plugboard settings by inspection. And the ring position is not taken into account: this affects when the middle rotor steps. If your output is correct for a bit, and then goes wrong, adjust the ring and start position on the right-hand rotor together until the output improves. If necessary, repeat for the middle rotor.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Bombe";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
|
@ -63,13 +63,24 @@ class Bombe extends Operation {
|
|||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Offset",
|
||||
name: "Crib offset",
|
||||
type: "number",
|
||||
value: 0
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and send a status update message.
|
||||
* @param {number} nLoops - Number of loops in the menu
|
||||
* @param {number} nStops - How many stops so far
|
||||
* @param {number} progress - Progress (as a float in the range 0..1)
|
||||
*/
|
||||
updateStatus(nLoops, nStops, progress) {
|
||||
const msg = `Bombe run with ${nLoops} loops in menu (2+ desirable): ${nStops} stops, ${Math.floor(100 * progress)}% done`;
|
||||
self.sendStatusMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
|
@ -77,7 +88,7 @@ class Bombe extends Operation {
|
|||
*/
|
||||
run(input, args) {
|
||||
const reflectorstr = args[4];
|
||||
const crib = args[5];
|
||||
let crib = args[5];
|
||||
const offset = args[6];
|
||||
const rotors = [];
|
||||
for (let i=0; i<4; i++) {
|
||||
|
@ -95,14 +106,18 @@ class Bombe extends Operation {
|
|||
if (crib.length === 0) {
|
||||
throw new OperationError("Crib cannot be empty");
|
||||
}
|
||||
input = input.replace(/[^A-Za-z]/g, "");
|
||||
if (offset < 0) {
|
||||
throw new OperationError("Offset cannot be negative");
|
||||
}
|
||||
// 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 reflector = new Reflector(reflectorstr);
|
||||
let update;
|
||||
try {
|
||||
update = self.sendStatusMessage;
|
||||
} catch (e) {
|
||||
// Happens when running headless
|
||||
if (ENVIRONMENT_IS_WORKER()) {
|
||||
update = this.updateStatus;
|
||||
} else {
|
||||
update = undefined;
|
||||
}
|
||||
const bombe = new BombeMachine(rotors, reflector, ciphertext, crib, update);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue