enigma
Version:
Implementation of an enigma machine
359 lines (254 loc) • 9.62 kB
JavaScript
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.enigma=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var Enigma = require('./lib/enigma');
var Rotor = require('./lib/rotor');
var Umkehrwalze = require('./lib/umkehrwalze');
var Eintrittswalze = require('./lib/eintrittswalze');
var Steckerbrett = require('./lib/steckerbrett');
module.exports = {
Enigma: Enigma,
Rotor: Rotor,
Umkehrwalze: Umkehrwalze,
Reflector: Umkehrwalze,
Eintrittswalze: Eintrittswalze,
EntryWheel: Eintrittswalze,
Steckerbrett: Steckerbrett,
Plugboard: Steckerbrett
};
},{"./lib/eintrittswalze":2,"./lib/enigma":3,"./lib/rotor":4,"./lib/steckerbrett":5,"./lib/umkehrwalze":6}],2:[function(require,module,exports){
var Walze = require('./walze');
module.exports = Eintrittswalze;
function Eintrittswalze(wiring, name) {
this.setWiring(wiring);
this.setName(name);
return this;
}
Eintrittswalze.prototype = new Walze();
},{"./walze":7}],3:[function(require,module,exports){
module.exports = Enigma;
function Enigma(rotors, ukw, steckerbrett, etw) {
this.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
if ( (rotors.length < 3 || rotors.length > 4) || typeof ukw === 'undefined' || typeof steckerbrett === 'undefined' || typeof etw === 'undefined') {
throw new Error('Only three or four rotors are supported, and reflector, plugboard and entry wheel must be set');
}
this.rotors = rotors;
this.ukw = ukw;
this.steckerbrett = steckerbrett;
this.etw = etw;
return this;
}
Enigma.prototype.signal = function(signal) {
// Rotate by 1 step
this.rotate();
// Send signal through the Steckerbrett
signal = this.steckerbrett.signal(signal);
// Send signal through the Eintrittswalze
signal = this.etw.signal(signal);
// Send signal through every rotor
for (var i = this.rotors.length - 1; i >= 0; i--) {
signal = this.rotors[i].signal(signal);
}
// Send signal through the Umkehrwalze
signal = this.ukw.signal(signal);
// Send signal through every rotor in reverse direction
for (var j = 0; j < this.rotors.length; j++) {
signal = this.rotors[j].signal(signal, true);
}
// Send signal through the Eintrittswalze in reverse direction
signal = this.etw.signal(signal, true);
// Send signal through the Steckerbrett in reverse direction
signal = this.steckerbrett.signal(signal, true);
return signal;
};
Enigma.prototype.rotate = function() {
var notched = [];
var turned = [];
for (var i = 0; i < this.rotors.length; i++) {
turned[i] = false;
notched.push( this.rotors[i].inNotch() );
}
for (var j = this.rotors.length - 1; j >= 0; j--) {
if ( (j === this.rotors.length - 1) || ( turned[j+1] && notched[j+1] ) || ( turned[j+1] && notched[j] && j > 0 ) ) {
this.rotors[j].rotate();
turned[j] = true;
}
}
};
Enigma.prototype.string = function(string) {
// Convert argument to string, upper case, and remove illegal letters (such as spaces)
string = typeof string === 'string' ? string : string.toString();
string = string.toUpperCase().replace(new RegExp('[^' + this.etw.wiring + ']','g'), '').split('');
var res = '';
for (var i = 0; i < string.length; i++) {
res += this.signal(string[i]);
}
return res;
};
Enigma.prototype.getPositions = function(){
var str = '';
for (var i = 0; i < this.rotors.length; i++) {
str += this.rotors[i].getPosition();
}
return str;
};
Enigma.prototype.setPositions = function(positions) {
positions = positions.split('');
for (var i = 0; i < this.rotors.length; i++) {
this.rotors[i].setPosition(positions[i]);
}
};
Enigma.prototype.getRingSettings = function() {
var str = '';
for (var i = 0; i < this.rotors.length; i++) {
str += this.rotors[i].getRingSetting();
}
return str;
};
Enigma.prototype.setRingSettings = function(settings) {
settings = settings.split('');
for (var i = 0; i < this.rotors.length; i++) {
this.rotors[i].setRingSetting(settings[i]);
}
};
},{}],4:[function(require,module,exports){
var Walze = require('./walze');
module.exports = Rotor;
function Rotor(wiring, notches, name) {
this.position = 0; // Enigmas start with 01
this.ringsetting = 0; // ring setting - Ringstellung
this.setWiring(wiring);
this.setNotches(notches);
this.setName(name);
return this;
}
Rotor.prototype = new Walze();
Rotor.prototype.signal = function(signal, reverse) {
var pos;
pos = this.alphabet.indexOf(signal);
pos = ( pos + this.position + (this.alphabet.length) - this.ringsetting) % (this.alphabet.length);
signal = this.alphabet[pos];
if ( reverse ) pos = this.wiring.indexOf(signal);
signal = reverse ? this.alphabet[pos] : this.wiring[pos];
pos = this.alphabet.indexOf(signal);
pos = ( pos + ( (this.alphabet.length) - this.position + this.ringsetting ) ) % (this.alphabet.length);
signal = this.alphabet[pos];
return signal;
};
Rotor.prototype.rotate = function() {
this.position = (this.position + 1) % (this.alphabet.length);
};
Rotor.prototype.inNotch = function() {
var inNotch = false;
for (var i = 0; i < this.notches.length; i++) {
if( this.position === this.alphabet.indexOf(this.notches[i]) ) {
inNotch = true;
break;
}
}
return inNotch;
};
Rotor.prototype.setNotches = function(notches) {
if ( typeof notches === 'string' ) {
notches = notches.toUpperCase().split('');
} else if ( typeof notches === 'object' && notches instanceof Array ) {
notches = notches.map(function(e) {
return e.toString().toUpperCase();
});
} else {
notches = [];
}
if ( notches.some( function(e,i,l){ return l.indexOf(e) !== l.lastIndexOf(e);} ) ) {
throw new Error('notches has to consist of unique characters');
}
if ( notches.length > this.alphabet.length ) {
throw new Error('you can’t have more notches than characters on the rotor');
}
this.notches = notches;
};
Rotor.prototype.getPosition = function() {
return this.alphabet[this.position];
};
Rotor.prototype.setPosition = function(position) {
this.position = this.alphabet.indexOf(position);
};
Rotor.prototype.getRingSetting = function() {
return this.alphabet[this.ringsetting];
};
Rotor.prototype.setRingSetting = function(setting) {
this.ringsetting = this.alphabet.indexOf(setting);
};
},{"./walze":7}],5:[function(require,module,exports){
var Walze = require('./walze');
module.exports = Steckerbrett;
function Steckerbrett(plugs, name) {
this.setName(name);
this.setPlugs(plugs);
return this;
}
Steckerbrett.prototype = new Walze();
Steckerbrett.prototype.setPlugs = function(plugs) {
if ( typeof plugs === 'string' ) {
plugs = plugs.toUpperCase().split(' ');
} else if ( typeof plugs === 'object' && plugs instanceof Array ) {
plugs = plugs.map(function(e) {
return e.toString().toUpperCase();
});
} else {
plugs = [];
}
var wiring = this.alphabet.slice();
for (var i = 0; i < plugs.length; i++) {
var plug = plugs[i].split('');
wiring[ this.alphabet.indexOf(plug[0]) ] = plug[1];
wiring[ this.alphabet.indexOf(plug[1]) ] = plug[0];
}
if ( wiring.length > this.alphabet.length || plugs.length > Math.floor( this.alphabet.length/2 ) ) {
throw new Error('The Steckerbrett only allows for ' + Math.floor( this.alphabet.length/2 ) + ' connections to be set');
}
this.setWiring(wiring);
};
},{"./walze":7}],6:[function(require,module,exports){
var Walze = require('./walze');
module.exports = Umkehrwalze;
function Umkehrwalze(wiring, name) {
this.setWiring(wiring);
this.setName(name);
return this;
}
Umkehrwalze.prototype = new Walze();
},{"./walze":7}],7:[function(require,module,exports){
module.exports = Walze;
function Walze(wiring, name) {
this.setWiring(wiring);
this.setName(name);
return this;
}
Walze.prototype.alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
Walze.prototype.setWiring = function(wiring) {
if ( typeof wiring === 'string' ) {
wiring = wiring.toUpperCase().split('');
} else if ( typeof wiring === 'object' && wiring instanceof Array ) {
wiring = wiring.map(function(e) {
return e.toString().toUpperCase();
});
} else {
wiring = this.alphabet.slice();
}
if ( wiring.some(function(e,i,l){ return l.indexOf(e) !== l.lastIndexOf(e);}) || wiring.length !== this.alphabet.length ) {
throw new Error('The Walze must have ' + (this.alphabet.length) + ' unique characters.');
}
this.wiring = wiring;
};
Walze.prototype.setName = function(name) {
if ( 'string' === typeof name) {
this.name = name;
} else {
this.name = '';
}
};
Walze.prototype.signal = function(signal, reverse) {
var pos = reverse ? this.wiring.indexOf(signal) : this.alphabet.indexOf(signal);
signal = reverse ? this.alphabet[pos] : this.wiring[pos];
return signal;
};
},{}]},{},[1])(1)
});