@ondoher/enigma 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +75 -48
  2. package/dist/index.d.ts +899 -0
  3. package/jsconfig.json +7 -1
  4. package/lib/enigma/Encoder.js +154 -12
  5. package/lib/enigma/Enigma.js +45 -59
  6. package/lib/enigma/EnigmaTypes.d.ts +115 -18
  7. package/lib/enigma/EntryDisc.js +2 -8
  8. package/lib/enigma/PlugBoard.js +4 -9
  9. package/lib/enigma/Reflector.js +5 -9
  10. package/lib/enigma/Rotor.js +43 -36
  11. package/lib/enigma/index.js +1 -1
  12. package/lib/enigma/tests/EnigmaSpec.js +21 -15
  13. package/lib/enigma/tests/RotorData.js +1 -1
  14. package/lib/enigma/tests/RotorSpec.js +3 -1
  15. package/lib/generator/CodeBook.js +3 -3
  16. package/lib/generator/Generator.js +6 -5
  17. package/lib/generator/GeneratorTypes.d.ts +2 -1
  18. package/lib/utils/Random.js +1 -1
  19. package/package.json +8 -2
  20. package/scripts/EnigmaData.js +236 -0
  21. package/scripts/hamlet.html +8880 -0
  22. package/scripts/make-validated-data.js +4 -0
  23. package/scripts/parseHamlet.js +32 -0
  24. package/scripts/test-messages.js +60 -0
  25. package/scripts/test.js +118 -0
  26. package/scripts/x +6446 -0
  27. package/tsconfig.json +19 -0
  28. package/types/enigma/Encoder.d.ts +128 -0
  29. package/types/enigma/Enigma.d.ts +88 -0
  30. package/types/enigma/EntryDisc.d.ts +17 -0
  31. package/types/enigma/Inventory.d.ts +91 -0
  32. package/types/enigma/PlugBoard.d.ts +26 -0
  33. package/types/enigma/Reflector.d.ts +14 -0
  34. package/types/enigma/Rotor.d.ts +59 -0
  35. package/types/enigma/consts.d.ts +1 -0
  36. package/types/enigma/index.d.ts +5 -0
  37. package/types/enigma/standardInventory.d.ts +71 -0
  38. package/types/enigma/tests/EnigmaData.d.ts +46 -0
  39. package/types/enigma/tests/EnigmaSpec.d.ts +1 -0
  40. package/types/enigma/tests/PlugBoardData.d.ts +4 -0
  41. package/types/enigma/tests/PlugBoardSpec.d.ts +1 -0
  42. package/types/enigma/tests/RotorData.d.ts +15 -0
  43. package/types/enigma/tests/RotorSpec.d.ts +1 -0
  44. package/types/generator/CodeBook.d.ts +82 -0
  45. package/types/generator/Generator.d.ts +67 -0
  46. package/types/generator/hamlet.d.ts +2 -0
  47. package/types/generator/index.d.ts +3 -0
  48. package/types/index.d.ts +899 -0
  49. package/types/utils/Random.d.ts +131 -0
@@ -17,8 +17,8 @@ export default class Rotor extends Encoder {
17
17
  * define the the rotor and how it is configured.
18
18
  */
19
19
  constructor(name, settings) {
20
- super(name, settings);
21
- var { map = STANDARD_ALPHABET, turnovers = '', ringSetting = 0} = settings
20
+ super(name, "Rotor", settings);
21
+ let { map = STANDARD_ALPHABET, turnovers = '', ringSetting = 0} = settings
22
22
 
23
23
  this.map = [...map];
24
24
  this.rightMap = this.makeMap(map);
@@ -29,10 +29,13 @@ export default class Rotor extends Encoder {
29
29
  this.turnoverLookup = this.makeMap(turnovers);
30
30
  this.offset = 0;
31
31
  if (turnovers === '') this.fixed = true;
32
- this.turnovers = this.turnoverLookup.reduce(function(turnovers, turnover) {
33
- turnovers[turnover] = true;
32
+ this.turnovers = turnovers;
33
+ /** @type {Set<number>} */
34
+ let turnoverSet = new Set();
35
+ this._turnovers = this.turnoverLookup.reduce((turnovers, turnover) => {
36
+ turnovers.add(turnover)
34
37
  return turnovers;
35
- }.bind(this), {});
38
+ }, turnoverSet);
36
39
  }
37
40
 
38
41
  /**
@@ -45,7 +48,7 @@ export default class Rotor extends Encoder {
45
48
  * ring setting.
46
49
  */
47
50
  setStartPosition(connector) {
48
- var pos = this.alphabet.indexOf(connector);
51
+ let pos = this.alphabet.indexOf(connector);
49
52
  this.offset = this.normalize(pos - this.ringOffset);
50
53
  }
51
54
 
@@ -56,61 +59,57 @@ export default class Rotor extends Encoder {
56
59
  * connector for the rotor's zero point we need to adjust the connector
57
60
  * number for the current rotation.
58
61
  *
59
- * @param {String} direction either right for moving towards the reflector or
62
+ * @param {Direction} direction either right for moving towards the reflector or
60
63
  * left if moving back
61
64
  * @param {Number} input the connector in physical space
62
65
  *
63
66
  * @returns {Number} the output connector in physical space.
64
67
  */
65
68
  encode(direction, input) {
66
- var map = direction === 'right' ? this.rightMap : this.leftMap;
67
- var evName = direction === 'right' ? 'encode-right' : 'encode-left';
69
+ let map = direction === 'right' ? this.rightMap : this.leftMap;
68
70
 
69
71
  //find the logical position of the input connector in the wiring map
70
- var index = this.normalize(input + this.offset);
72
+ let index = this.normalize(input + this.offset);
71
73
 
72
74
  // get the logical output connector and convert that to the physical
73
75
  // output connector
74
- var output = map[index];
75
- var result = this.normalize(output - this.offset);
76
-
77
- this.fire(evName, this.name,
78
- `${evName} ${this.name}, input: ${input} output: ${result} relative input: ${index}, relative output: ${output} rotation: ${this.offset}`,
79
- {
80
- input : input,
81
- output: result,
82
- logicalInput: index,
83
- logicalOutput: output,
84
- rotation: this.offset,
85
- }
86
- );
76
+ let output = map[index];
77
+ let result = this.normalize(output - this.offset);
87
78
 
79
+ this.fireEncodeSet(input, result, direction);
88
80
  return result;
89
81
  }
90
82
 
91
83
  /**
92
84
  * Call this method to step the rotor
93
85
  *
94
- * @returns {Boolean} true true if the next rotor should be stepped
86
+ * @returns {Boolean} true if the next rotor should be stepped
95
87
  */
96
88
  step() {
97
89
  // Because the turnover notch is attached to the outer ring, and the
98
90
  // logical coordinates are based on the wiring, the logical position of
99
91
  // the notch for turnover needs to be adjusted to remove the ring offset.
92
+ let start = this.offset;
100
93
  this.offset = this.normalize(this.offset + 1);
101
- var turnoverOffset = this.normalize(this.offset + this.ringOffset);
94
+ let stop = this.offset;
95
+ let turnoverOffset = this.normalize(this.offset + this.ringOffset);
96
+
102
97
 
103
98
  // turnover happens when we step past the turnover point
104
- var turnover = this.turnovers[this.normalize(turnoverOffset - 1)];
99
+ let turnover = this._turnovers.has(this.normalize(turnoverOffset - 1));
100
+ let turnoverStr = turnover ? 'with turnover' : ''
101
+
102
+ /** @type {EventData} */
103
+ let eventData = {
104
+ name: this.name,
105
+ type: this.type,
106
+ description: `Rotor "${this.name}" stepped from ${start} to ${stop}${turnoverStr}`,
107
+ event: 'step',
108
+ turnover, start, stop
109
+ }
105
110
 
106
- this.fire('step', this.name,
107
- `step ${this.name}, ${this.offset} ${this.normalize(this.offset + this.ringOffset)} ${turnoverOffset} ${Boolean(turnover)}`,
108
- {
109
- rotation: this.offset,
110
- ringSetting: this.ringOffset,
111
- turnover: Boolean(turnover),
112
- }
113
- );
111
+ // console.log("firing", eventData);
112
+ this.fire('step', this.name, eventData);
114
113
 
115
114
  return turnover;
116
115
  }
@@ -123,10 +122,18 @@ export default class Rotor extends Encoder {
123
122
  * @returns true if this rotor will turnover on the next step
124
123
  */
125
124
  willTurnover() {
126
- var turnoverOffset = this.normalize(this.offset + this.ringOffset);
125
+ let turnoverOffset = this.normalize(this.offset + this.ringOffset);
127
126
 
128
127
  // double stepping happens when we step to the turnover point
129
- return this.turnovers[turnoverOffset];
128
+ return this._turnovers.has(turnoverOffset);
129
+ }
130
+
131
+ shouldTurnover() {
132
+ let turnoverOffset = this.normalize(this.offset + 1 + this.ringOffset);
133
+
134
+ // double stepping happens when we step to the turnover point
135
+ return this._turnovers.has(turnoverOffset);
136
+
130
137
  }
131
138
 
132
139
  /**
@@ -1,5 +1,5 @@
1
1
  export {default as Enigma} from './Enigma.js';
2
- export {default as EntryDisc} from './EntryDisk.js';
2
+ export {default as EntryDisc} from './EntryDisc.js';
3
3
  export {default as inventory} from './Inventory.js';
4
4
  export {default as PlugBoard} from './PlugBoard.js';
5
5
  export {default as Reflector} from './Rotor.js';
@@ -5,11 +5,12 @@ import Enigma from "../Enigma.js";
5
5
  import { enigmaData } from './EnigmaData.js';
6
6
 
7
7
  describe('Enigma Test Cases', function() {
8
+ /** @type {Enigma} */
8
9
  var enigma;
9
10
 
10
11
  function messageLoop(messages, which, cb) {
11
12
  return messages.find(function(message) {
12
- var enigma = new Enigma({
13
+ var enigma = new Enigma("Test", {
13
14
  reflector: message.setup.reflector
14
15
  });
15
16
 
@@ -20,7 +21,7 @@ describe('Enigma Test Cases', function() {
20
21
  })
21
22
 
22
23
  var toEncode = message.message[which]
23
- var encoded = enigma.encode(message.message.key,toEncode);
24
+ var encoded = enigma.translate(message.message.key,toEncode);
24
25
 
25
26
  return cb(message, encoded);
26
27
  })
@@ -29,39 +30,42 @@ describe('Enigma Test Cases', function() {
29
30
  describe('Stepping', function() {
30
31
  var steps = {}
31
32
  beforeEach(function() {
32
- enigma = new Enigma({
33
+ enigma = new Enigma("I", {
33
34
  reflector: 'B',
34
35
  });
35
36
 
36
37
  enigma.configure({rotors: ['I', 'II', 'III']});
37
38
 
38
- enigma.listen(function(event, name, message, info) {
39
+ listen()
40
+ });
41
+
42
+ function listen() {
43
+ enigma.listen('test', (event, name, data) => {
39
44
  if (event === 'step') {
40
45
  steps[name] = steps[name] || [];
41
- steps[name].push(info);
46
+ steps[name].push(data);
42
47
  }
43
48
  })
44
-
45
- });
49
+ }
46
50
 
47
51
  it ('should step only the right-most rotor when not at turnover', function() {
48
52
  steps = {};
49
- enigma.encode('AAA', 'A');
53
+ enigma.translate('AAA', 'A');
50
54
  var stepped = Object.keys(steps);
51
55
  expect(stepped.length).toBe(1);
52
- expect(stepped[0]).toBe('rotor-III');
56
+ expect(stepped[0]).toBe('III');
53
57
  });
54
58
 
55
59
  it ('should step the next rotor when the previous turns over', function() {
56
60
  steps = {};
57
- enigma.encode('AAV', 'A');
58
- expect(steps['rotor-II'].length).toBe(1);
61
+ enigma.translate('AAV', 'A');
62
+ expect(steps['II'].length).toBe(1);
59
63
  });
60
64
 
61
65
  it ('should double step when reaching the turn over', function() {
62
66
  steps = {};
63
- enigma.encode('ADV', 'AA');
64
- expect(steps['rotor-II'].length).toBe(2);
67
+ enigma.translate('ADV', 'AA');
68
+ expect(steps['II'].length).toBe(2);
65
69
  });
66
70
 
67
71
  it ('should double step on first step', function() {
@@ -69,8 +73,10 @@ describe('Enigma Test Cases', function() {
69
73
 
70
74
  enigma.configure({rotors: ['III', 'VI', 'VIII'], ringSettings: [1, 8, 13]});
71
75
 
72
- enigma.encode('UZV', 'AA');
73
- expect(steps['rotor-VI'].length).toBe(1);
76
+ listen();
77
+
78
+ enigma.translate('UZV', 'AA');
79
+ expect(steps['VI'].length).toBe(1);
74
80
  });
75
81
  })
76
82
 
@@ -4,7 +4,7 @@ export const rotorData = {
4
4
  map: 'BCDA',
5
5
  reverseMap: [3, 0, 1, 2],
6
6
  turnovers: 'AM',
7
- turnoversMap: {0: true, 12: true}
7
+ turnoversMap: [0, 12]
8
8
  },
9
9
  I: {
10
10
  map: 'EKMFLGDQVZNTOWYHXUSPAIBRCJ',
@@ -29,7 +29,9 @@ describe('Rotor Test Cases', function() {
29
29
  turnovers: rotorData.createData.turnovers,
30
30
  });
31
31
 
32
- expect(rotor.turnovers).toEqual(rotorData.createData.turnoversMap);
32
+ let turnovers = [...rotor._turnovers];
33
+
34
+ expect(turnovers).toEqual(rotorData.createData.turnoversMap);
33
35
  })
34
36
  })
35
37
 
@@ -108,11 +108,11 @@ export default class CodeBook {
108
108
 
109
109
  let key = Random.choose(3, [...STANDARD_ALPHABET]).join('');
110
110
  let start = Random.choose(3, [...STANDARD_ALPHABET]).join('');
111
- let enc = this.enigma.encode(key, start);
111
+ let enc = this.enigma.translate(key, start);
112
112
  let clear = text;
113
113
 
114
114
  text = text.replace(/ /g, '');
115
- text = this.enigma.encode(start, text);
115
+ text = this.enigma.translate(start, text);
116
116
  text = this.generator.groupText(text);
117
117
  text = paddedIndicator + ' ' + text
118
118
 
@@ -155,7 +155,7 @@ export default class CodeBook {
155
155
  });
156
156
 
157
157
  return {
158
- options: this.enigma.configuration,
158
+ configuration: this.enigma.configuration,
159
159
  parts: messages
160
160
  }
161
161
  }
@@ -109,9 +109,9 @@ export default class Generator {
109
109
  let useRotors = structuredClone(setup.rotors || unfixed);
110
110
  let rotors = Random.pick(3, useRotors);
111
111
  let ringSettings = Random.choose(3, connectors);
112
- let plugsList = Random.pickPairs(10, letters);
112
+ let plugsPairs = Random.pickPairs(10, letters);
113
113
 
114
- plugsList = plugsList.map((pair) => pair.join(""));
114
+ let plugsList = plugsPairs.map((pair) => pair.join(""));
115
115
 
116
116
  ringSettings[0]++;
117
117
  ringSettings[1]++;
@@ -136,7 +136,7 @@ export default class Generator {
136
136
  */
137
137
  createRandomEnigma(model = "Enigma", reflectors = ['A', 'B', 'C']) {
138
138
  let reflector = Random.pickOne(reflectors);
139
- return new Enigma({model, reflector});
139
+ return new Enigma(model, {model, reflector});
140
140
  }
141
141
 
142
142
  /**
@@ -153,8 +153,9 @@ export default class Generator {
153
153
  let decoded = this.cleanMessage(this.generateSentences(count));
154
154
  let start = Random.choose(enigma.rotors.length, [...STANDARD_ALPHABET]).join('');
155
155
 
156
- let encoded = enigma.encode(start, decoded);
156
+ let encoded = enigma.translate(start, decoded);
157
157
 
158
- return {start, encoded, decoded, configuration: enigma.configuration};
158
+ return {start, encoded, decoded,
159
+ configuration: enigma.configuration};
159
160
  }
160
161
  }
@@ -89,12 +89,13 @@ type GeneratedMessage = {
89
89
  encoded: string;
90
90
  /** the decoded string */
91
91
  decoded: string;
92
+ configuration?: SimplifiedConfiguration;
92
93
  }
93
94
 
94
95
  type Model = ("I" | "M3" | "M4");
95
96
 
96
97
  type ModelOptions = {
97
98
  rotors: string[];
98
- fixed: string[];
99
+ fixed: string[] | boolean;
99
100
  reflectors: string[];
100
101
  }
@@ -147,7 +147,7 @@ class Random {
147
147
  * two items from the list
148
148
  */
149
149
  pickPairs(count, list) {
150
- /** @type {[T, T][]} */
150
+ /** @type {T[][]} */
151
151
  let result = [];
152
152
 
153
153
  for(let idx = 0; idx < count; idx++) {
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@ondoher/enigma",
3
- "version": "1.0.2",
4
- "description": "Enigma machine simulator implementation with tools and documentation to help you build your own.",
3
+ "version": "1.0.5",
4
+ "description": "Enigma machine simulator with tools and documentation to help you build your own.",
5
5
  "main": "./lib/index.js",
6
+ "types": "./types/index.d.ts",
6
7
  "scripts": {
7
8
  "test": "jasmine"
8
9
  },
@@ -25,7 +26,12 @@
25
26
  "homepage": "https://github.com/Ondoher/enigma#readme",
26
27
  "type": "module",
27
28
  "devDependencies": {
29
+ "@types/node": "^25.0.10",
28
30
  "jasmine": "^4.5.0",
29
31
  "jasmine-console-reporter": "^3.1.0"
32
+ },
33
+ "dependencies": {
34
+ "@types/jasmine": "^4.6.6",
35
+ "undici-types": "^7.19.0"
30
36
  }
31
37
  }
@@ -0,0 +1,236 @@
1
+ export const enigmaData = {
2
+ sampleFieldMessages: [
3
+ {
4
+ source: 'http://wiki.franklinheath.co.uk/index.php/Enigma/Sample_Decrypts#Operation_Barbarossa.2C_1941',
5
+ model: 'I/M3',
6
+ setup: {
7
+ reflector: 'B',
8
+ rotors: ['II', 'IV', 'V'],
9
+ ringSettings: [2, 21, 12],
10
+ plugs: 'AV BS CG DL FU HZ IN KM OW RX'
11
+ },
12
+ message: {
13
+ key: 'BLA',
14
+ encoded: 'EDPUDNRGYSZRCXNUYTPOMRMBOFKTBZREZKMLXLVEFGUEYSIOZVEQMIKUBPMMYLKLTTDEISMDICAGYKUACTCDOMOHWXMUUIAUBSTSLRNBZSZWNRFXWFYSSXJZVIJHIDISHPRKLKAYUPADTXQSPINQMATLPIFSVKDASCTACDPBOPVHJK',
15
+ decoded: 'AUFKLXABTEILUNGXVONXKURTINOWAXKURTINOWAXNORDWESTLXSEBEZXSEBEZXUAFFLIEGERSTRASZERIQTUNGXDUBROWKIXDUBROWKIXOPOTSCHKAXOPOTSCHKAXUMXEINSAQTDREINULLXUHRANGETRETENXANGRIFFXINFXRGTX',
16
+ }
17
+ },
18
+ {
19
+ source: 'http://wiki.franklinheath.co.uk/index.php/Enigma/Sample_Messages#U-264_.28Kapit.C3.A4nleutnant_Hartwig_Looks.29.2C_1942',
20
+ model: 'M4',
21
+ setup: {
22
+ reflector: 'Thin-B',
23
+ rotors: ['Beta', 'II', 'IV', 'I'],
24
+ ringSettings: [1, 1, 1, 22],
25
+ plugs: 'AT BL DF GJ HM NW OP QY RZ VX',
26
+ },
27
+ message: {
28
+ key: 'VJNA',
29
+ encoded: 'NCZWVUSXPNYMINHZXMQXSFWXWLKJAHSHNMCOCCAKUQPMKCSMHKSEINJUSBLKIOSXCKUBHMLLXCSJUSRRDVKOHULXWCCBGVLIYXEOAHXRHKKFVDREWEZLXOBAFGYUJQUKGRTVUKAMEURBVEKSUHHVOYHABCJWMAKLFKLMYFVNRIZRVVRTKOFDANJMOLBGFFLEOPRGTFLVRHOWOPBEKVWMUQFMPWPARMFHAGKXIIBG',
30
+ decoded: 'VONVONJLOOKSJHFFTTTEINSEINSDREIZWOYYQNNSNEUNINHALTXXBEIANGRIFFUNTERWASSERGEDRUECKTYWABOSXLETZTERGEGNERSTANDNULACHTDREINULUHRMARQUANTONJOTANEUNACHTSEYHSDREIYZWOZWONULGRADYACHTSMYSTOSSENACHXEKNSVIERMBFAELLTYNNNNNNOOOVIERYSICHTEINSNULL',
31
+ }
32
+ },
33
+ {
34
+ source: 'http://wiki.franklinheath.co.uk/index.php/Enigma/Sample_Messages#Scharnhorst_.28Konteradmiral_Erich_Bey.29.2C_1943',
35
+ model: 'M3',
36
+ setup: {
37
+ reflector: 'B',
38
+ rotors: ['III', 'VI', 'VIII'],
39
+ ringSettings: [1, 8, 13],
40
+ plugs: 'AN EZ HK IJ LR MQ OT PV SW UX',
41
+ },
42
+ message: {
43
+ key: 'UZV',
44
+ encoded: 'YKAENZAPMSCHZBFOCUVMRMDPYCOFHADZIZMEFXTHFLOLPZLFGGBOTGOXGRETDWTJIQHLMXVJWKZUASTR',
45
+ decoded: 'STEUEREJTANAFJORDJANSTANDORTQUAAACCCVIERNEUNNEUNZWOFAHRTZWONULSMXXSCHARNHORSTHCO',
46
+ }
47
+ },
48
+ {
49
+ source: 'https://enigma.hoerenberg.com/index.php?cat=The%20U534%20messages&page=P1030662',
50
+ model: 'M4',
51
+ setup: {
52
+ reflector: 'Thin-C',
53
+ rotors: ['Beta', 'V', 'VI', 'VIII'],
54
+ ringSettings: 'AAEL',
55
+ plugs: 'AE BF CM DQ HU JN LX PR SZ VW',
56
+ },
57
+ message: {
58
+ key: 'WIIJ',
59
+ encoded: 'LIRZMLWRCDMSNKLKBEBHRMFQFEQAZWXBGBIEXJPYFCQAAWSEKDEACOHDZKCZTOVSYHFNSCMAIMIMMAVJNLFXEWNPUIRINOZNCRVDHCGKCYRVUJQPVKEUIVVXGLQMKRJMDMLXLLRLYBKJWRXBQRZWGCCNDOPMGCKJ',
60
+ decoded: 'UUUVIRSIBENNULEINSYNACHRXUUUSTUETZPUNKTLUEBECKVVVCHEFVIERXUUUFLOTTXXMITUUUVIERSIBENNULZWOUNDUUUVIERSIBENNULDREIZURFLENDERWERFTLUEBECKGEHENXFONDORTFOLGTWEITERESX',
61
+ }
62
+ },
63
+ {
64
+ source: 'https://enigma.hoerenberg.com/index.php?cat=Norrk%C3%B6ping%20messages&page=PAGE_47_DOEP',
65
+ model: 'M3',
66
+ setup: {
67
+ reflector: 'B',
68
+ rotors: ['VII', 'IV', 'VI'],
69
+ ringSettings: 'AGW',
70
+ plugs: 'BM DX EW GP JO KV NZ RT',
71
+ },
72
+ message: {
73
+ key: 'NSH',
74
+ encoded: 'YEWZANTGDXWUVDSSYQELAMUOAMBVFZAJWFATABRMMBWXWTLFIOYBTEXXFFAOHADDXWWGBEROYDWLEUTP',
75
+ decoded: 'KOFFERGRAMOPHONKEINSINNKTZCMYQWPJDZXQLXGJXKWXLQDHYKCMIRBYKFHCMQWHVXLRHGDXMQWCHYK',
76
+ }
77
+ },
78
+ {
79
+ source: 'https://enigma.hoerenberg.com/index.php?cat=Norrk%C3%B6ping%20messages&page=PAGE_49_KRLR',
80
+ model: 'M3',
81
+ setup: {
82
+ reflector: 'B',
83
+ rotors: ['VII', 'IV', 'VI'],
84
+ ringSettings: 'AGW',
85
+ plugs: 'BM DX EW GP JO KV NZ RT',
86
+ },
87
+ message: {
88
+ key: 'RPR',
89
+ encoded: 'PBQOMEWLLMJFBXKPZNBHRGLUGVHJBXYPSEACOXOTBQRWVTPVVYHLLDOCQQKIWVAMJNFADSUNAVMJGJIBMUGBWWRKJBZNHVELOGZHTISLTUWS',
90
+ decoded: 'VERWALTUNGSAMTREICHSGERICHTARBEITSLAGERNICHTAUFSCHLAGENVCNSTDMQWZVGNVMBCPDGKPFQZWTRLDMFNGHSRDTFZGLDKCVLMNHGF',
91
+
92
+ }
93
+
94
+ }
95
+ ],
96
+ sampleVerifiedMessages: [
97
+ {
98
+ verified: ['https://cryptii.com/pipes/enigma-machine', ],
99
+ model: 'I',
100
+ setup: {
101
+ rotors: ['II', 'IV', 'III'],
102
+ plugs: 'IU ZM NK YH SJ DB TX RF OG QE',
103
+ ringSettings: [22, 26, 26],
104
+ reflector: 'A'
105
+ },
106
+ message: {
107
+ key: 'ZAE',
108
+ encoded: 'EICSSVSACTFYCNWRBCXMELAKMTBDSSPAIHMUKGFDPVEUHUDWRKOTITUTNWCEJTGUUGVVBOSVOYIDXHBRFYNOAJWISOZDIOPIXJDJJXBUYJWQRMMACUDGZCVHIFPRPCUDDWTXLCEUEASBRVOUFRTQDDOWWGCIEQSAYEXYHLCJHKWRMNQUHERAEGUXBQQDWIZYQHFJZRBZBNGWPUGLUYMUCXFKPPBWXAPRRXZLWBOFPWQHKVXWKHTNJXQCZZROWMYPLSMJINVBUCIPVYZGZXMONPMEIFWALQFEKJRRJYXVRNUFWNMPMIYBCQCJNSLNHIHOESEVNFMBKPPQTWQXQMCKIMQNPGOOTKNJDBKKHTWDUSJJGTSFJJLQ',
109
+ decoded: 'HOWOTHERWISETHEKINGSIRHATHLAIDTHATINADOZENPASSESBETWEENYOURSELFANDHIMHESHALLNOTEXCEEDYOUTHREEHITSHEHATHLAIDONTWELVEFORNINEANDITWOULDCOMETOIMMEDIATETRIALIFYOURLORDSHIPWOULDVOUCHSAFETHEANSWERBYTHELORDHORATIOTHESETHREEYEARSIHAVETAKENANOTEOFITTHEAGEISGROWNSOPICKEDTHATTHETOEOFTHEPEASANTCOMESSONEARTHEHEELOFTHECOURTIERHEGAFFSHISKIBETHYSTATEISTHEMOREGRACIOUSFORTISAVICETOKNOWHIM'
110
+ }
111
+
112
+ },
113
+ {
114
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'http://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v26_en.html'],
115
+ model: 'I',
116
+ setup: {
117
+ rotors: ['III', 'IV', 'I'],
118
+ plugs: 'EL ID YR QP FX HO KJ NS BV WU',
119
+ ringSettings: [10, 22, 8],
120
+ reflector: 'B'
121
+ },
122
+ message: {
123
+ key: 'OAK',
124
+ encoded: 'RXDVNGAFUCJOOJHUZZKLZLCIVQZQUJYGRAQSUQWSWFCGJXGDGWWQMTYTLLLGTLWVCSQQITTKGOEDMERMCMPERRYAZKEDRFSDKWVQUSMGFXLJFOWKIUMTJXKQDBHGPJUKQRTSBTZ',
125
+ decoded: 'GOODEVENSIRMAYONEBEPARDONDANDRETAINTHEOFFENCEHOWLONGHATHSHEBEENTHUSTHOUGHTANDAFFLICTIONPASSIONHELLITSELFSHETURNSTOFAVOURANDTOPRETTINESS'
126
+ }
127
+
128
+ },
129
+ {
130
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'http://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v26_en.html'],
131
+ model: 'I',
132
+ setup: {
133
+ rotors: ['III', 'I', 'II'],
134
+ plugs: 'EJ ZX TU KV MI DB NW GQ LR FO',
135
+ ringSettings: [4, 5, 7],
136
+ reflector: 'B'
137
+ },
138
+ message: {
139
+ start: 'OEC',
140
+ encoded: 'WCOJLTOXJZSYRDRGPLWJJOXWFCCISIRBMEHOKYWDFNJFWXCWATBJJTJLTMEQMWBIFXVIBJJOPAYKSUZIFATKZLMMVHNIYOPHBYKBAAHCYPKELSEWGKBHAHROMIGPBRYQXFCRJGUXWHFKBGTECDZDZLWVIHXKOFBXWJKETDLBLWKDTPPFUFKPKMROJHZMDDBHTKXSWMPNRYOVWEEUIMKYBGVSQJCFNBKKLVYZGKQQRTMMPTWJAMJQPGDCGHLUNQKSVWOAALTXS',
141
+ decoded: 'HOWDANGEROUSISITTHATTHISMANGOESLOOSEYETMUSTNOTWEPUTTHESTRONGLAWONHIMHESLOVEDOFTHEDISTRACTEDMULTITUDEWHOLIKENOTINTHEIRJUDGMENTBUTTHEIREYESANDWHERETISSOTHEOFFENDERSSCOURGEISWEIGHDBUTNEVERTHEOFFENCEAMINOTITHERIGHTOLDJEPHTHAHAHMYGOODLORDWHATHAVEISEENTONIGHTWHATGERTRUDE'
142
+ }
143
+
144
+ },
145
+ {
146
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'http://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v26_en.html'],
147
+ model: 'M3',
148
+ setup: {
149
+ rotors: ['IV', 'VII', 'I'],
150
+ plugs: 'NI RM AH VQ UL FD GS WY JE TX',
151
+ ringSettings: [23, 13, 3],
152
+ reflector: 'B'
153
+ },
154
+ message: {
155
+ start: 'HMP',
156
+ encoded: 'PDWBCHJGYPCHHUXNDVUGEZSYIUATENCFMYUIQPWIBBIELWXUNAWZNPVNKTBOJTHEDWDJJKQEOEPSMJBRGTWJGNURUXXEFYGJKUSHYPFZIDEWODCRKXFFLQKVLRLXNIACDAZEIFJXTLZXUSJRLQIDBJTIDUAFRJAYTSNFBJBXKVLASUZQMPCJJLCOZDMDIRPEJANYQCIUPLAPSMQMXXXHSMMNEDCSDDILZOWGPXVWKWKHKYLXEOYFHMNBPURLKA',
157
+ decoded: 'COMEHITHERGENTLEMENANDLAYYOURHANDSAGAINUPONMYSWORDNEVERTOSPEAKOFTHISTHATYOUHAVEHEARDSWEARBYMYSWORDAREYOUFAIRNOMOREBEDONEWESHOULDPROFANETHESERVICEOFTHEDEADTOSINGAREQUIEMANDSUCHRESTTOHERASTOPEACEPARTEDSOULSNIGGARDOFQUESTIONBUTOFOURDEMANDSMOSTFREEINHISREPLY'
158
+ }
159
+ },
160
+ {
161
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'http://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v26_en.html'],
162
+ model: 'M3',
163
+ setup: {
164
+ rotors: ['VI', 'IV', 'II'],
165
+ plugs: 'QZ DK LA MX ET BG VO SH YP WJ',
166
+ ringSettings: [4, 15, 21],
167
+ reflector: 'B'
168
+ },
169
+ message: {
170
+ key: 'ASA',
171
+ encoded: 'URVTSTZATDUFQLGIUJKVRRVJZHSHDOGEKHREOYECTDTBUYZACWNGMHTUGWNUIUJMKHQQAPAKQIQYDHXWBRILLAURPOYTGNYUDANCLJCKSIPCJWLCLBHVXKNNRXPHHJUQJMRBZZASHQLCLQMMTYOA',
172
+ decoded: 'EXCHANGEFORGIVENESSWITHMENOBLEHAMLETMINEANDMYFATHERSDEATHCOMENOTUPONTHEENORTHINEONMEHORATIOIAMDEADTHOULIVESTREPORTMEANDMYCAUSEARIGHTTOTHEUNSATISFIED'
173
+ }
174
+ },
175
+ {
176
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'http://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-u_v26_en.html'],
177
+ model: 'M3',
178
+ setup: {
179
+ rotors: ['II', 'I', 'VII'],
180
+ plugs: 'BL SK WD FN HZ IX QU EJ PC OM',
181
+ ringSettings: [19, 20, 14],
182
+ reflector: 'B'
183
+ },
184
+ message: {
185
+ key: 'HRO',
186
+ encoded: 'LJVBCURJWLPLFSYKZNBEXTUHTPCWRQTOKBRBCDMAMQCDMIXIOMVCVKBVDXMXIJVELDNRBXPWCCICPEHAXTVZYV',
187
+ decoded: 'WHYONEFAIRDAUGHTERANDNOMORETHEWHICHHELOVEDPASSINGWELLYOUTOLDUSOFSOMESUITWHATISTLAERTES'
188
+ }
189
+ },
190
+ {
191
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-m4_v16_en.html'],
192
+ model: 'M4',
193
+ setup: {
194
+ rotors: ['Beta', 'II', 'VII', 'V'],
195
+ plugs: 'YL SF VO AI BX WC KD MT JN PH',
196
+ ringSettings: [9, 18, 12, 8],
197
+ reflector: 'Thin-B'
198
+ },
199
+ message: {
200
+ key: 'MKDM',
201
+ encoded: 'KEKZCUAFFTWOHZURZPCTWWCICFOGAXBTCTPHMAIFXEEBAYFCQOOAGFKWAHOFEUYWBUEZIWADYATCTLEOUGRPSQDTBZCHIGQGBCXBRYDSGFDBEURKHUKFUYHALYROROKIZWFTPEJJUIRGBIQFGPLGWXJPMNPSEHYSGITZCGSMZXVVJCRXZQWGMOKNBTYVRMYHPWMEXGPUSHYQEWIDZTITRUFXLPYAQUCZVDCAVCMWGGQMXEQDFPTBLOJDEGTGKXXWFIGASTKMLWHFOPPXNBVDYUHDNOJNATOTMWLJGLSTJXDDHGKOBZCPNTPLPKINICEWVJUUNVKDYWGVFFJE',
202
+ decoded: 'YOUNGFORTINBRASWITHCONQUESTCOMEFROMPOLANDTOTHEAMBASSADORSOFENGLANDGIVESTHISWARLIKEVOLLEYNOUPSWORDANDKNOWTHOUAMOREHORRIDHENTWHENHEISDRUNKASLEEPORINHISRAGEORINTHEINCESTUOUSPLEASUREOFHISBEDATGAMINGSWEARINGORABOUTSOMEACTTHATHASNORELISHOFSALVATIONINTTHENTRIPHIMTHATHISHEELSMAYKICKATHEAVENANDTHATHISSOULMAYBEASDAMNDANDBLACKASHELLWHERETOITGOES'
203
+ }
204
+ },
205
+ {
206
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-m4_v16_en.html'],
207
+ model: 'M4',
208
+ setup: {
209
+ rotors: ['Gamma', 'VIII', 'VI', 'V'],
210
+ plugs: 'RX VA HE ST QL UK PG DB JZ OC',
211
+ ringSettings: [7, 14, 19, 26],
212
+ reflector: 'Thin-C'
213
+ },
214
+ message: {
215
+ key: 'IBFP',
216
+ encoded: 'PUEDVIRAVXYTNFBCUGMSVLVZYRREYMERJCSCKSCACKBZNZNNLYFAAUIKFRMIIUPWBFSFWVKRYLMKHXKXGJXRFQJNRSLSFGFBBKEVQPWCLKUBMNUUKWIYSUQXAXOGZKSBVCRXMIMNJKOXCUBFXSGYQVUXSAWOFQVDQIYTULXKZXEKCQGXQXFVADTSSVZZGQMHBBMJQBYLUWAJELOIYICWTDZQAQYPBCAGKHTICILGFKMNRRXGRUTADCIOCQBXHODIRWXARKENICHVMVHWRRIVWWDCG',
217
+ decoded: 'IFYOUDOMEETHORATIOANDMARCELLUSTHERIVALSOFMYWATCHBIDTHEMMAKEHASTETHEGREATMANDOWNYOUMARKHISFAVOURITEFLIESTHEPOORADVANCEDMAKESFRIENDSOFENEMIESOWONDERFULGOODMYLORDTELLITFORGIVEMETHISMYVIRTUEFORINTHEFATNESSOFTHESEPURSYTIMESVIRTUEITSELFOFVICEMUSTPARDONBEGYEACURBANDWOOFORLEAVETODOHIMGOOD'
218
+ }
219
+ },
220
+ {
221
+ verified: ['https://cryptii.com/pipes/enigma-machine', 'https://people.physik.hu-berlin.de/~palloks/js/enigma/enigma-m4_v16_en.html'],
222
+ model: 'M4',
223
+ setup: {
224
+ rotors: ['Gamma', 'II', 'VIII', 'VII'],
225
+ plugs: 'SA LM XY CV ER GB KT PJ WH DU',
226
+ ringSettings: [25, 21, 11, 2],
227
+ reflector: 'Thin-B'
228
+ },
229
+ message: {
230
+ key: 'TQXV',
231
+ encoded: 'NWWKWEOXQKVGAFEMANRTAEGIZIROXKLPEFTWZJEHQVXDIDDXYIDASSXZJUSZTDHEUKPUVNTOONBYOZJAGCMTEFYHCSJCHOHGMXWHLZAVCBRVNGAMTFUNZNVWPAWBXUICZCYKDBSKJZBQPOMBJCJVKSIGJXAXBDZLYAGPSVATCLXXEQVIWUKBOP',
232
+ decoded: 'COMEHITHERGENTLEMENANDLAYYOURHANDSAGAINUPONMYSWORDNEVERTOSPEAKOFTHISTHATYOUHAVEHEARDSWEARBYMYSWORDSEEITSTALKSAWAYSTAYSPEAKSPEAKICHARGETHEESPEAKTISGONEANDWILLNOTANSWERISHALLOBEYMYLORD'
233
+ }
234
+ }
235
+ ]
236
+ }