mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-24 16:56:15 -04:00
Added operation description note and modified comment formatting
This commit is contained in:
parent
3c68ad1302
commit
88947b9d42
3 changed files with 193 additions and 188 deletions
|
@ -1,15 +1,14 @@
|
|||
/**
|
||||
Emulation of the SIGABA machine
|
||||
|
||||
@author hettysymes
|
||||
@copyright hettysymes 2020
|
||||
@license Apache-2.0
|
||||
*/
|
||||
* Emulation of the SIGABA machine
|
||||
*
|
||||
* @author hettysymes
|
||||
* @copyright hettysymes 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
|
||||
*/
|
||||
|
||||
* A set of randomised example SIGABA cipher/control rotors (these rotors are interchangeable). Cipher and control rotors can be referred to as C and R rotors respectively.
|
||||
*/
|
||||
export const CR_ROTORS = [
|
||||
{name: "Example 1", value: "SRGWANHPJZFXVIDQCEUKBYOLMT"},
|
||||
{name: "Example 2", value: "THQEFSAZVKJYULBODCPXNIMWRG"},
|
||||
|
@ -24,9 +23,8 @@ export const CR_ROTORS = [
|
|||
];
|
||||
|
||||
/**
|
||||
A set of randomised example SIGABA index rotors (may be referred to as I rotors).
|
||||
*/
|
||||
|
||||
* A set of randomised example SIGABA index rotors (may be referred to as I rotors).
|
||||
*/
|
||||
export const I_ROTORS = [
|
||||
{name: "Example 1", value: "6201348957"},
|
||||
{name: "Example 2", value: "6147253089"},
|
||||
|
@ -38,11 +36,11 @@ export const I_ROTORS = [
|
|||
export const NUMBERS = "0123456789".split("");
|
||||
|
||||
/**
|
||||
Converts a letter to uppercase (if it already isn't)
|
||||
|
||||
@param {char} letter - letter to convert to upper case
|
||||
@returns {char}
|
||||
*/
|
||||
* Converts a letter to uppercase (if it already isn't)
|
||||
*
|
||||
* @param {char} letter - letter to convert to uppercase
|
||||
* @returns {char}
|
||||
*/
|
||||
export function convToUpperCase(letter) {
|
||||
const charCode = letter.charCodeAt();
|
||||
if (97<=charCode && charCode<=122) {
|
||||
|
@ -52,16 +50,17 @@ export function convToUpperCase(letter) {
|
|||
}
|
||||
|
||||
/**
|
||||
The SIGABA machine consisting of the 3 rotor banks: cipher, control and index banks.
|
||||
*/
|
||||
* The SIGABA machine consisting of the 3 rotor banks: cipher, control and index banks.
|
||||
*/
|
||||
export class SigabaMachine {
|
||||
/**
|
||||
SigabaMachine constructor
|
||||
|
||||
@param {Object[]} cipherRotors - list of CRRotors
|
||||
@param {Object[]} controlRotors - list of CRRotors
|
||||
@param {object[]} indexRotors - list of IRotors
|
||||
*/
|
||||
/**
|
||||
* SigabaMachine constructor
|
||||
*
|
||||
* @param {Object[]} cipherRotors - list of CRRotors
|
||||
* @param {Object[]} controlRotors - list of CRRotors
|
||||
* @param {object[]} indexRotors - list of IRotors
|
||||
*/
|
||||
constructor(cipherRotors, controlRotors, indexRotors) {
|
||||
this.cipherBank = new CipherBank(cipherRotors);
|
||||
this.controlBank = new ControlBank(controlRotors);
|
||||
|
@ -69,8 +68,8 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
Steps all the correct rotors in the machine.
|
||||
*/
|
||||
* Steps all the correct rotors in the machine.
|
||||
*/
|
||||
step() {
|
||||
const controlOut = this.controlBank.goThroughControl();
|
||||
const indexOut = this.indexBank.goThroughIndex(controlOut);
|
||||
|
@ -78,11 +77,11 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
Encrypts a letter. A space is converted to a "Z" before encryption, and a "Z" is converted to an "X". This allows spaces to be encrypted.
|
||||
|
||||
@param {char} letter - letter to encrypt
|
||||
@returns {char}
|
||||
*/
|
||||
* Encrypts a letter. A space is converted to a "Z" before encryption, and a "Z" is converted to an "X". This allows spaces to be encrypted.
|
||||
*
|
||||
* @param {char} letter - letter to encrypt
|
||||
* @returns {char}
|
||||
*/
|
||||
encryptLetter(letter) {
|
||||
letter = convToUpperCase(letter);
|
||||
if (letter === " ") {
|
||||
|
@ -96,11 +95,11 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
Decrypts a letter. A letter decrypted as a "Z" is converted to a space before it is output, since spaces are converted to "Z"s before encryption.
|
||||
|
||||
@param {char} letter - letter to decrypt
|
||||
@returns {char}
|
||||
*/
|
||||
* Decrypts a letter. A letter decrypted as a "Z" is converted to a space before it is output, since spaces are converted to "Z"s before encryption.
|
||||
*
|
||||
* @param {char} letter - letter to decrypt
|
||||
* @returns {char}
|
||||
*/
|
||||
decryptLetter(letter) {
|
||||
letter = convToUpperCase(letter);
|
||||
let decryptedLetter = this.cipherBank.decrypt(letter);
|
||||
|
@ -112,11 +111,11 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
Encrypts a message of one or more letters
|
||||
|
||||
@param {string} msg - message to encrypt
|
||||
@returns {string}
|
||||
*/
|
||||
* Encrypts a message of one or more letters
|
||||
*
|
||||
* @param {string} msg - message to encrypt
|
||||
* @returns {string}
|
||||
*/
|
||||
encrypt(msg) {
|
||||
let ciphertext = "";
|
||||
for (const letter of msg) {
|
||||
|
@ -126,11 +125,11 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
Decrypts a message of one or more letters
|
||||
|
||||
@param {string} msg - message to decrypt
|
||||
@returns {string}
|
||||
*/
|
||||
* Decrypts a message of one or more letters
|
||||
*
|
||||
* @param {string} msg - message to decrypt
|
||||
* @returns {string}
|
||||
*/
|
||||
decrypt(msg) {
|
||||
let plaintext = "";
|
||||
for (const letter of msg) {
|
||||
|
@ -142,24 +141,25 @@ export class SigabaMachine {
|
|||
}
|
||||
|
||||
/**
|
||||
The cipher rotor bank consists of 5 cipher rotors in either a forward or reversed orientation.
|
||||
*/
|
||||
* The cipher rotor bank consists of 5 cipher rotors in either a forward or reversed orientation.
|
||||
*/
|
||||
export class CipherBank {
|
||||
/**
|
||||
CipherBank constructor
|
||||
|
||||
@param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
/**
|
||||
* CipherBank constructor
|
||||
*
|
||||
* @param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = rotors;
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts a letter through the cipher rotors (signal goes from left-to-right)
|
||||
|
||||
@param {char} inputPos - the input position of the signal (letter to be encrypted)
|
||||
@returns {char}
|
||||
*/
|
||||
* Encrypts a letter through the cipher rotors (signal goes from left-to-right)
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal (letter to be encrypted)
|
||||
* @returns {char}
|
||||
*/
|
||||
encrypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos, "leftToRight");
|
||||
|
@ -168,11 +168,11 @@ export class CipherBank {
|
|||
}
|
||||
|
||||
/**
|
||||
Decrypts a letter through the cipher rotors (signal goes from right-to-left)
|
||||
|
||||
@param {char} inputPos - the input position of the signal (letter to be decrypted)
|
||||
@returns {char}
|
||||
*/
|
||||
* Decrypts a letter through the cipher rotors (signal goes from right-to-left)
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal (letter to be decrypted)
|
||||
* @returns {char}
|
||||
*/
|
||||
decrypt(inputPos) {
|
||||
const revOrderedRotors = [...this.rotors].reverse();
|
||||
for (const rotor of revOrderedRotors) {
|
||||
|
@ -182,10 +182,10 @@ export class CipherBank {
|
|||
}
|
||||
|
||||
/**
|
||||
Step the cipher rotors forward according to the inputs from the index rotors
|
||||
|
||||
@param {number[]} indexInputs - the inputs from the index rotors
|
||||
*/
|
||||
* Step the cipher rotors forward according to the inputs from the index rotors
|
||||
*
|
||||
* @param {number[]} indexInputs - the inputs from the index rotors
|
||||
*/
|
||||
step(indexInputs) {
|
||||
const logicDict = {0: [0, 9], 1: [7, 8], 2: [5, 6], 3: [3, 4], 4: [1, 2]};
|
||||
const rotorsToMove = [];
|
||||
|
@ -206,24 +206,25 @@ export class CipherBank {
|
|||
}
|
||||
|
||||
/**
|
||||
The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
|
||||
*/
|
||||
* The control rotor bank consists of 5 control rotors in either a forward or reversed orientation. Signals to the control rotor bank always go from right-to-left.
|
||||
*/
|
||||
export class ControlBank {
|
||||
/**
|
||||
ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
|
||||
|
||||
@param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
/**
|
||||
* ControlBank constructor. The rotors have been reversed as signals go from right-to-left through the control rotors.
|
||||
*
|
||||
* @param {Object[]} rotors - list of CRRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = [...rotors].reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts a letter.
|
||||
|
||||
@param {char} inputPos - the input position of the signal
|
||||
@returns {char}
|
||||
*/
|
||||
* Encrypts a letter.
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal
|
||||
* @returns {char}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos, "rightToLeft");
|
||||
|
@ -232,10 +233,10 @@ export class ControlBank {
|
|||
}
|
||||
|
||||
/**
|
||||
Gets the outputs of the control rotors. The inputs to the control rotors are always "F", "G", "H" and "I".
|
||||
|
||||
@returns {number[]}
|
||||
*/
|
||||
* Gets the outputs of the control rotors. The inputs to the control rotors are always "F", "G", "H" and "I".
|
||||
*
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getOutputs() {
|
||||
const outputs = [this.crypt("F"), this.crypt("G"), this.crypt("H"), this.crypt("I")];
|
||||
const logicDict = {1: "B", 2: "C", 3: "DE", 4: "FGH", 5: "IJK", 6: "LMNO", 7: "PQRST", 8: "UVWXYZ", 9: "A"};
|
||||
|
@ -253,8 +254,8 @@ export class ControlBank {
|
|||
}
|
||||
|
||||
/**
|
||||
Steps the control rotors. Only 3 of the control rotors step: one after every encryption, one after every 26, and one after every 26 squared.
|
||||
*/
|
||||
* Steps the control rotors. Only 3 of the control rotors step: one after every encryption, one after every 26, and one after every 26 squared.
|
||||
*/
|
||||
step() {
|
||||
const MRotor = this.rotors[1], FRotor = this.rotors[2], SRotor = this.rotors[3];
|
||||
// 14 is the offset of "O" from "A" - the next rotor steps once the previous rotor reaches "O"
|
||||
|
@ -268,10 +269,10 @@ export class ControlBank {
|
|||
}
|
||||
|
||||
/**
|
||||
The goThroughControl function combines getting the outputs from the control rotor bank and then stepping them.
|
||||
|
||||
@returns {number[]}
|
||||
*/
|
||||
* The goThroughControl function combines getting the outputs from the control rotor bank and then stepping them.
|
||||
*
|
||||
* @returns {number[]}
|
||||
*/
|
||||
goThroughControl() {
|
||||
const outputs = this.getOutputs();
|
||||
this.step();
|
||||
|
@ -281,24 +282,25 @@ export class ControlBank {
|
|||
}
|
||||
|
||||
/**
|
||||
The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
|
||||
*/
|
||||
* The index rotor bank consists of 5 index rotors all placed in the forwards orientation.
|
||||
*/
|
||||
export class IndexBank {
|
||||
/**
|
||||
IndexBank constructor
|
||||
|
||||
@param {Object[]} rotors - list of IRotors
|
||||
*/
|
||||
/**
|
||||
* IndexBank constructor
|
||||
*
|
||||
* @param {Object[]} rotors - list of IRotors
|
||||
*/
|
||||
constructor(rotors) {
|
||||
this.rotors = rotors;
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts a number.
|
||||
|
||||
@param {number} inputPos - the input position of the signal
|
||||
@returns {number}
|
||||
*/
|
||||
* Encrypts a number.
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal
|
||||
* @returns {number}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
for (const rotor of this.rotors) {
|
||||
inputPos = rotor.crypt(inputPos);
|
||||
|
@ -307,11 +309,11 @@ export class IndexBank {
|
|||
}
|
||||
|
||||
/**
|
||||
The goThroughIndex function takes the inputs from the control rotor bank and returns the list of outputs after encryption through the index rotors.
|
||||
|
||||
@param {number[]} - inputs from the control rotors
|
||||
@returns {number[]}
|
||||
*/
|
||||
* The goThroughIndex function takes the inputs from the control rotor bank and returns the list of outputs after encryption through the index rotors.
|
||||
*
|
||||
* @param {number[]} controlInputs - inputs from the control rotors
|
||||
* @returns {number[]}
|
||||
*/
|
||||
goThroughIndex(controlInputs) {
|
||||
const outputs = [];
|
||||
for (const inp of controlInputs) {
|
||||
|
@ -323,16 +325,17 @@ export class IndexBank {
|
|||
}
|
||||
|
||||
/**
|
||||
Rotor class
|
||||
*/
|
||||
* Rotor class
|
||||
*/
|
||||
export class Rotor {
|
||||
/**
|
||||
Rotor constructor
|
||||
|
||||
@param {number[]} wireSetting - the wirings within the rotor: mapping from left-to-right, the index of the number in the list maps onto the number at that index
|
||||
@param {bool} rev - true if the rotor is reversed, false if it isn't
|
||||
@param {number} key - the starting position or state of the rotor
|
||||
*/
|
||||
/**
|
||||
* Rotor constructor
|
||||
*
|
||||
* @param {number[]} wireSetting - the wirings within the rotor: mapping from left-to-right, the index of the number in the list maps onto the number at that index
|
||||
* @param {bool} rev - true if the rotor is reversed, false if it isn't
|
||||
* @param {number} key - the starting position or state of the rotor
|
||||
*/
|
||||
constructor(wireSetting, key, rev) {
|
||||
this.state = key;
|
||||
this.numMapping = this.getNumMapping(wireSetting, rev);
|
||||
|
@ -340,12 +343,12 @@ export class Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
Get the number mapping from the wireSetting (only different from wireSetting if rotor is reversed)
|
||||
|
||||
@param {number[]} wireSetting - the wirings within the rotors
|
||||
@param {bool} rev - true if reversed, false if not
|
||||
@returns {number[]}
|
||||
*/
|
||||
* Get the number mapping from the wireSetting (only different from wireSetting if rotor is reversed)
|
||||
*
|
||||
* @param {number[]} wireSetting - the wirings within the rotors
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getNumMapping(wireSetting, rev) {
|
||||
if (rev===false) {
|
||||
return wireSetting;
|
||||
|
@ -360,11 +363,11 @@ export class Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
Get the position mapping (how the position numbers map onto the numbers of the rotor)
|
||||
|
||||
@param {bool} rev - true if reversed, false if not
|
||||
@returns {number[]}
|
||||
*/
|
||||
* Get the position mapping (how the position numbers map onto the numbers of the rotor)
|
||||
*
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
* @returns {number[]}
|
||||
*/
|
||||
getPosMapping(rev) {
|
||||
const length = this.numMapping.length;
|
||||
const posMapping = [];
|
||||
|
@ -389,12 +392,12 @@ export class Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
Encrypt/decrypt data. This process is identical to the rotors of cipher machines such as Enigma or Typex.
|
||||
|
||||
@param {number} inputPos - the input position of the signal (the data to encrypt/decrypt)
|
||||
@param {string} direction - one of "leftToRight" and "rightToLeft", states the direction in which the signal passes through the rotor
|
||||
@returns {number}
|
||||
*/
|
||||
* Encrypt/decrypt data. This process is identical to the rotors of cipher machines such as Enigma or Typex.
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal (the data to encrypt/decrypt)
|
||||
* @param {string} direction - one of "leftToRight" and "rightToLeft", states the direction in which the signal passes through the rotor
|
||||
* @returns {number}
|
||||
*/
|
||||
cryptNum(inputPos, direction) {
|
||||
const inpNum = this.posMapping[inputPos];
|
||||
let outNum;
|
||||
|
@ -408,8 +411,8 @@ export class Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
Steps the rotor. The number at position 0 will be moved to position 1 etc.
|
||||
*/
|
||||
* Steps the rotor. The number at position 0 will be moved to position 1 etc.
|
||||
*/
|
||||
step() {
|
||||
const lastNum = this.posMapping.pop();
|
||||
this.posMapping.splice(0, 0, lastNum);
|
||||
|
@ -419,49 +422,49 @@ export class Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
|
||||
*/
|
||||
* A CRRotor is a cipher (C) or control (R) rotor. These rotors are identical and interchangeable. A C or R rotor consists of 26 contacts, one for each letter, and may be put into either a forwards of reversed orientation.
|
||||
*/
|
||||
export class CRRotor extends Rotor {
|
||||
|
||||
/**
|
||||
CRRotor constructor
|
||||
|
||||
@param {string} wireSetting - the rotor wirings (string of letters)
|
||||
@param {char} key - initial state of rotor
|
||||
@param {bool} rev - true if reversed, false if not
|
||||
*/
|
||||
* CRRotor constructor
|
||||
*
|
||||
* @param {string} wireSetting - the rotor wirings (string of letters)
|
||||
* @param {char} key - initial state of rotor
|
||||
* @param {bool} rev - true if reversed, false if not
|
||||
*/
|
||||
constructor(wireSetting, key, rev=false) {
|
||||
wireSetting = wireSetting.split("").map(CRRotor.letterToNum);
|
||||
super(wireSetting, CRRotor.letterToNum(key), rev);
|
||||
}
|
||||
|
||||
/**
|
||||
Static function which converts a letter into its number i.e. its offset from the letter "A"
|
||||
|
||||
@param {char} letter - letter to convert to number
|
||||
@returns {number}
|
||||
*/
|
||||
* Static function which converts a letter into its number i.e. its offset from the letter "A"
|
||||
*
|
||||
* @param {char} letter - letter to convert to number
|
||||
* @returns {number}
|
||||
*/
|
||||
static letterToNum(letter) {
|
||||
return letter.charCodeAt()-65;
|
||||
}
|
||||
|
||||
/**
|
||||
Static function which converts a number (a letter's offset from "A") into its letter
|
||||
|
||||
@param {number} num - number to convert to letter
|
||||
@returns {char}
|
||||
*/
|
||||
* Static function which converts a number (a letter's offset from "A") into its letter
|
||||
*
|
||||
* @param {number} num - number to convert to letter
|
||||
* @returns {char}
|
||||
*/
|
||||
static numToLetter(num) {
|
||||
return String.fromCharCode(num+65);
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts/decrypts a letter.
|
||||
|
||||
@param {char} inputPos - the input position of the signal ("A" refers to position 0 etc.)
|
||||
@param {string} direction - one of "leftToRight" and "rightToLeft"
|
||||
@returns {char}
|
||||
*/
|
||||
* Encrypts/decrypts a letter.
|
||||
*
|
||||
* @param {char} inputPos - the input position of the signal ("A" refers to position 0 etc.)
|
||||
* @param {string} direction - one of "leftToRight" and "rightToLeft"
|
||||
* @returns {char}
|
||||
*/
|
||||
crypt(inputPos, direction) {
|
||||
inputPos = CRRotor.letterToNum(inputPos);
|
||||
const outPos = this.cryptNum(inputPos, direction);
|
||||
|
@ -471,26 +474,27 @@ export class CRRotor extends Rotor {
|
|||
}
|
||||
|
||||
/**
|
||||
An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
|
||||
*/
|
||||
* An IRotor is an index rotor, which consists of 10 contacts each numbered from 0 to 9. Unlike C and R rotors, they cannot be put in the reversed orientation. The index rotors do not step at any point during encryption or decryption.
|
||||
*/
|
||||
export class IRotor extends Rotor {
|
||||
/**
|
||||
IRotor constructor
|
||||
|
||||
@param {string} wireSetting - the rotor wirings (string of numbers)
|
||||
@param {char} key - initial state of rotor
|
||||
*/
|
||||
/**
|
||||
* IRotor constructor
|
||||
*
|
||||
* @param {string} wireSetting - the rotor wirings (string of numbers)
|
||||
* @param {char} key - initial state of rotor
|
||||
*/
|
||||
constructor(wireSetting, key) {
|
||||
wireSetting = wireSetting.split("").map(Number);
|
||||
super(wireSetting, Number(key), false);
|
||||
}
|
||||
|
||||
/**
|
||||
Encrypts a number
|
||||
|
||||
@param {number} inputPos - the input position of the signal
|
||||
@returns {number}
|
||||
*/
|
||||
* Encrypts a number
|
||||
*
|
||||
* @param {number} inputPos - the input position of the signal
|
||||
* @returns {number}
|
||||
*/
|
||||
crypt(inputPos) {
|
||||
return this.cryptNum(inputPos, "leftToRight");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue