Skip to content

Commit

Permalink
Added brute_force.js, added documentation to readme.
Browse files Browse the repository at this point in the history
  • Loading branch information
Stuart Rutter committed Mar 13, 2013
1 parent a548e30 commit e84cf5d
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 12 deletions.
32 changes: 20 additions & 12 deletions README.md
@@ -1,12 +1,10 @@
==================
| TypeX Emulation |
==================
# TypeX Emulation

This is a Javascript implementation of the British Cipher Machine - TypeX. I have translated this to Javascript from a [version written in C][1].
This is a Javascript implementation of the British Rotor Cipher Machine - [TypeX][2]. The Enigma has been used as a basis for this code as they have very similar workings, this version is a translation to Javascript from a [version written in C][1].

Improvements that I have made to the original code include:

1. It no longer uses files for input / output.
1. No longer relies on files for input / output.
2. I have broken down the transformation into a better (more readable) format:

The transformation steps are:
Expand All @@ -27,27 +25,33 @@ The transformation steps are:

3. I wrote this with the intention of using it in a brute force attack. To do this we can iterate through all possible rotor settings / orientations. Please see brute_force.js for an example.

4. Input validation has been modularised.
4. Input validation is cleaner.

5. Removed goto's, general housekeeping.

6. Speed is almost double to that of the C implementation due to caching and no file read / writes (which helps when it comes to brute forcing).

##### Example 1 - Encoding
```javascript
var demo1 = TypeX.init('01234', '00100', 'AOAKN', 'This is the string to be encoded');
console.log(demo1);
//demo1 == KLHESNYNIMQAZHIZROBHDZHKWRQFFRTY
```

##### Example 2 - Decoding
```javascript
var demo2 = TypeX.init('01234', '00100', 'AOAKN', 'KLHESNYNIMQAZHIZROBHDZHKWRQFFRTY');
console.log(demo2);
//demo2 == THISXISXTHEXSTRINGXTOXBEXENCODED
```

##### Brute Force

The code in brute_force.js loops through every possible rotor position and orientation. This assumes that we know the indicator key.
The code in brute_force.js loops through every possible rotor position and orientation. It then inserts (in batches) the results into a Mongo collection.

To run this Javascript you will need Node with the [native Mongo module][3] installed.

The brute force method assumes that we know the indicator key.

The indicator key is 5 letters (A-Z), that indicate the starting position of each rotor.

```javascript
//Rotor orientations (5^2)
Expand All @@ -73,8 +77,12 @@ if((/(\d)(?=.*\1)/).test(rotorPos)) continue;
var cipher_text = TypeX.init(rotorPos, rotorOri, 'AOAKN', 'KLHESNYNIMQAZHIZROBHDZHKWRQFFRTY');
```
In the above example, there are 215,000 possible rotor settings, of which we can harvest them into a database. We can then crawl this database and search for cribs, or we can perform a common bigram / trigram count which is probably an easier way to reduce this number.
In the above example, there are 215,000 possible rotor settings, we can then harvest them into a database for further processing.
We can then crawl this database and search for cribs, or we can perform a common bigram / trigram count which is probably an easier way to reduce this number.
See function ngram(str, n) in brute_force.js for an example of how to add these counts to your database.
See brute_force.js for an example of how to add an ngram count to your database.
[1]: http://scholarworks.sjsu.edu/cgi/viewcontent.cgi?article=1244&context=etd_projects
[1]: http://scholarworks.sjsu.edu/cgi/viewcontent.cgi?article=1244&context=etd_projects
[2]: http://en.wikipedia.org/wiki/Typex
[3]: https://github.com/mongodb/node-mongodb-native
123 changes: 123 additions & 0 deletions brute_force.js
@@ -0,0 +1,123 @@
require("./typex.js");

var mongo = require('mongodb');

var Inserter = function (collection) {
this.collection = collection;
this.data = [];
this.maxThreads = 30;
this.currentThreads = 0;
this.batchSize = 1000;
this.queue = 0;
this.inserted = 0;
this.startTime = Date.now();
};

Inserter.prototype.add = function(data) {
this.data.push(data);
};

// Use force=true for last insert
Inserter.prototype.insert = function(force) {
var that = this;
if (this.data.length >= this.batchSize || force) {
if (this.currentThreads >= this.maxThreads) {
this.queue++;
return;
}
this.currentThreads++;
console.log('Threads: ' + this.currentThreads);
this.collection.insert(this.data.splice(0, this.batchSize), {safe:true}, function() {
that.inserted += that.batchSize;
var currentTime = Date.now();
var workTime = Math.round((currentTime - that.startTime) / 1000)
console.log('Speed: ' + that.inserted / workTime + ' per sec');
that.currentThreads--;
if (that.queue > 0) {
that.queue--;
that.insert();
}
});
}
};

ngram = function(str,n) {
//http://norvig.com/mayzner.html
var ngrams = [[],[],
["th","he","in","er","an"], // 2grams
["the","and","ing","ion","tio"] // 3grams
];

var total = 0;
for (var i in ngrams[n]) {
var re = new RegExp(ngrams[n][i], 'gi');
if((didMatch = str.match(re))) {
total += didMatch.length;
}
}
return total;

};

var db = new mongo.Db('test', new mongo.Server('localhost', 27017, {w:1}), {native_parser:false});

db.open(function(err, db) {
db.collection('typexResults', function(err, collection) {

var inserter = new Inserter(collection);
var cipher_text = 'HVPKDFNFJWYIDDCRQXSRDJHFPGOVFNMIAPXPABUZWYYNPCMPNWHJRZHNLXKGMEMKKONOIBAKEEQWAOTARBQRHDJOFMTPZEHLKXGHRGGHTJRZCQFNKTQKLDTSFQIRW';
var indicator = 'AOAKN';
x = 0;

//Rotor orientations (5^2)
for (r1 = 0; r1 <= 1; r1++) {
for (r2 = 0; r2 <= 1; r2++) {
for (r3 = 0; r3 <= 1; r3++) {
for (r4 = 0; r4 <= 1; r4++) {
for (r5 = 0; r5 <= 1; r5++) {

//Rotor positions (5^7)
for (a = 0; a <=7; a++) {
for (b = 0; b <=7; b++) {
for (c = 0; c <=7; c++) {
for (d = 0; d <=7; d++) {
for (e = 0; e <=7; e++) {

rotorPos = a.toString() + b + c + d + e;
rotorOri = r1.toString() + r2 + r3 + r4 + r5;

if((/(\d)(?=.*\1)/).test(rotorPos)) continue;

var ct_val = TypeX.init(rotorPos, rotorOri, indicator, cipher_text);

inserter.add({
c_text: ct_val,
two_gram: ngram(ct_val,2),
three_gram: ngram(ct_val,3),
rotor_position: rotorPos,
rotor_orientation: rotorOri
});

if(x%5000===0) {
inserter.insert();
}

x++;

}
}
}
}
}

}
}
}
}
}

//Final batch insert
inserter.insert(true);

});
});

0 comments on commit e84cf5d

Please sign in to comment.