Created
June 28, 2013 17:09
-
-
Save arlolra/5886310 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/.jshintrc b/.jshintrc | |
index 62a53cf..8fcd5f7 100644 | |
--- a/.jshintrc | |
+++ b/.jshintrc | |
@@ -12,10 +12,13 @@ | |
, "white" : false | |
, "multistr" : true | |
, "globals" : { | |
- "it" : true | |
- , "beforeEach" : true | |
- , "before" : true | |
- , "describe" : true | |
- , "define" : true | |
+ "it" : true | |
+ , "beforeEach" : true | |
+ , "before" : true | |
+ , "describe" : true | |
+ , "define" : true | |
+ , "postMessage" : true | |
+ , "onmessage" : true | |
+ , "importScripts" : true | |
} | |
} | |
\ No newline at end of file | |
diff --git a/lib/otr.js b/lib/otr.js | |
index 02f28a4..0df67a7 100644 | |
--- a/lib/otr.js | |
+++ b/lib/otr.js | |
@@ -3,12 +3,15 @@ | |
var root = this | |
- var CryptoJS, BigInt, EventEmitter, CONST, HLP, Parse, AKE, SM, DSA | |
+ var CryptoJS, BigInt, EventEmitter, Worker, SMWPath | |
+ , CONST, HLP, Parse, AKE, SM, DSA | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = OTR | |
CryptoJS = require('../vendor/crypto.js') | |
BigInt = require('../vendor/bigint.js') | |
EventEmitter = require('../vendor/eventemitter.js').EventEmitter | |
+ Worker = require('webworker-threads').Worker | |
+ SMWPath = require('path').join(__dirname, '/sm-webworker.js') | |
CONST = require('./const.js') | |
HLP = require('./helpers.js') | |
Parse = require('./parse.js') | |
@@ -26,6 +29,8 @@ | |
CryptoJS = root.CryptoJS | |
BigInt = root.BigInt | |
EventEmitter = root.EventEmitter | |
+ Worker = root.Worker | |
+ SMWPath = 'sm-webworker.js' | |
CONST = OTR.CONST | |
HLP = OTR.HLP | |
Parse = OTR.Parse | |
@@ -72,6 +77,11 @@ | |
// debug | |
this.debug = !!options.debug | |
+ // smp in webworker options | |
+ this.sm_webworker = !!options.sm_webworker | |
+ this.seed_ww = (typeof options.seed_ww === 'function') ? | |
+ options.seed_ww : BigInt.getSeed | |
+ | |
// init vals | |
this.init() | |
@@ -142,7 +152,44 @@ | |
this.ssid = null | |
} | |
+ // smp over webworker | |
+ OTR.prototype._wwSM = function (otr) { | |
+ this.otr = otr | |
+ this.worker = new Worker(SMWPath) | |
+ this.worker.onmessage = function (e) { | |
+ console.log("Worker said : " + e.data) | |
+ } | |
+ this.worker.postMessage({ | |
+ type: 'seed' | |
+ , seed: otr.seed_ww() | |
+ }) | |
+ this.worker.postMessage({ | |
+ type: 'init' | |
+ , ssid: otr.ssid | |
+ , our_fp: otr.priv.fingerprint() | |
+ , their_fp: otr.their_priv_pk.fingerprint() | |
+ , msgstate: otr.msgstate | |
+ }) | |
+ } | |
+ | |
+ // shim sm methods | |
+ ;['handleSM', 'rcvSecret'].forEach(function (m) { | |
+ OTR.prototype._wwSM.prototype[m] = function () { | |
+ this.worker.postMessage({ | |
+ type: 'method' | |
+ , method: m | |
+ , args: Array.prototype.slice.call(arguments, 0) | |
+ , msgstate: this.otr.msgstate | |
+ }) | |
+ } | |
+ }) | |
+ | |
OTR.prototype._smInit = function () { | |
+ if (this.sm_webworker) { | |
+ if (this.sm) this.sm.close() // destroy prev webworker | |
+ this.sm = new this._wwSM(this) | |
+ return | |
+ } | |
this.sm = new SM(this) | |
} | |
diff --git a/lib/sm-webworker.js b/lib/sm-webworker.js | |
new file mode 100644 | |
index 0000000..95c1196 | |
--- /dev/null | |
+++ b/lib/sm-webworker.js | |
@@ -0,0 +1,75 @@ | |
+;(function (root) { | |
+ "use strict"; | |
+ | |
+ // ughhh | |
+ var seed = null | |
+ | |
+ root.OTR = {} | |
+ root.crypto = { | |
+ randomBytes: function () { return seed } | |
+ } | |
+ | |
+ function err() { | |
+ postMessage(arguments) | |
+ } | |
+ | |
+ function send() { | |
+ postMessage(arguments) | |
+ } | |
+ | |
+ function trigger() { | |
+ postMessage(arguments) | |
+ } | |
+ | |
+ var sm | |
+ onmessage = function (msg) { | |
+ var d = msg.data | |
+ switch(d.type) { | |
+ case 'seed': | |
+ seed = d.seed | |
+ try { | |
+ importScripts('vendor/salsa20.js') | |
+ importScripts('vendor/bigint.js') | |
+ importScripts('vendor/crypto.js') | |
+ importScripts('lib/const.js') | |
+ importScripts('lib/helpers.js') | |
+ importScripts('lib/sm.js') | |
+ } catch (e) { | |
+ console.log(e.stack) | |
+ } | |
+ console.log('done seeding') | |
+ break | |
+ case 'init': | |
+ try { | |
+ console.log('typeof') | |
+ console.log(typeof root.SM) | |
+ sm = new root.OTR.SM({ | |
+ debug: true | |
+ , trust: false | |
+ , sm_webworker: true | |
+ , ssid: d.ssid | |
+ , priv: { fingerprint: function () { return d.our_fp } } | |
+ , their_priv_pk: { fingerprint: function () { return d.their_fp } } | |
+ , msgstate: d.msgstate | |
+ , error: err | |
+ , trigger: trigger | |
+ , _sendMsg: send | |
+ }) | |
+ } catch (e) { | |
+ console.log(e.stack) | |
+ } | |
+ break | |
+ case 'method': | |
+ console.log(d) | |
+ console.log(sm) | |
+ sm.otr.msgstate = d.msgstate | |
+ console.log('here') | |
+ try { | |
+ sm[d.method].apply(sm, d.args) | |
+ } catch (e) { console.log(e.stack) } | |
+ console.log('done') | |
+ break | |
+ } | |
+ } | |
+ | |
+}(this)) | |
\ No newline at end of file | |
diff --git a/lib/sm.js b/lib/sm.js | |
index d3fa1da..7a61826 100644 | |
--- a/lib/sm.js | |
+++ b/lib/sm.js | |
@@ -3,21 +3,19 @@ | |
var root = this | |
- var CryptoJS, BigInt, CONST, HLP, DSA | |
+ var CryptoJS, BigInt, CONST, HLP | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = SM | |
CryptoJS = require('../vendor/crypto.js') | |
BigInt = require('../vendor/bigint.js') | |
CONST = require('./const.js') | |
HLP = require('./helpers.js') | |
- DSA = require('./dsa.js') | |
} else { | |
root.OTR.SM = SM | |
CryptoJS = root.CryptoJS | |
BigInt = root.BigInt | |
CONST = root.OTR.CONST | |
HLP = root.OTR.HLP | |
- DSA = root.DSA | |
} | |
// diffie-hellman modulus and generator | |
@@ -32,6 +30,8 @@ | |
function SM(otr) { | |
if (!(this instanceof SM)) return new SM(otr) | |
+ console.log('haha') | |
+ | |
this.otr = otr | |
this.version = '1' | |
this.our_fp = otr.priv.fingerprint() | |
@@ -342,6 +342,8 @@ | |
rcvSecret: function (secret, question) { | |
HLP.debug.call(this.otr, 'receive secret') | |
+ console.log('here') | |
+ | |
this.otr.trigger('status', [CONST.STATUS_SMP_SECRET]) | |
if (this.otr.msgstate !== CONST.MSGSTATE_ENCRYPTED) | |
diff --git a/package.json b/package.json | |
index e6d8fdc..679bfda 100644 | |
--- a/package.json | |
+++ b/package.json | |
@@ -20,6 +20,9 @@ | |
"socialist millionaire", | |
"dsa" | |
], | |
+ "optionalDependencies": { | |
+ "webworker-threads": "0.4.x" | |
+ }, | |
"devDependencies": { | |
"mocha": "1.10.x", | |
"simple-xmpp": "0.1.x", | |
diff --git a/test/spec/unit/sm.js b/test/spec/unit/sm.js | |
index 4586d74..dd2e183 100644 | |
--- a/test/spec/unit/sm.js | |
+++ b/test/spec/unit/sm.js | |
@@ -81,7 +81,6 @@ describe('SM', function () { | |
}) | |
- | |
it('2 should verify the SM secret failed', function (done) { | |
this.timeout(15000) | |
var both = false | |
@@ -169,4 +168,52 @@ describe('SM', function () { | |
}) | |
}) | |
+ it.only('4 should verify the SM secret in a webworker', function (done) { | |
+ this.timeout(15000) | |
+ var both = false | |
+ | |
+ // use webworkers | |
+ userA.sm_webworker = true | |
+ userB.sm_webworker = true | |
+ | |
+ userA.on('ui', function (msg) { assert.equal(false, !!msg, msg) }) | |
+ userA.on('error', function (err) { assert.equal(false, !!err, err) }) | |
+ | |
+ userA.on('status', function (state) { | |
+ if (state === CONST.STATUS_AKE_SUCCESS) { | |
+ assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted') | |
+ assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted') | |
+ assert.ok(!userA.trust, 'Trust B? false') | |
+ assert.ok(!userB.trust, 'Trust A? false') | |
+ userA.smpSecret('applesAndOranges') | |
+ } | |
+ }) | |
+ | |
+ userA.on('smp', function (type) { | |
+ if (type === 'trust') { | |
+ assert.ok(userA.trust, 'Trust B? false') | |
+ if (both) done() | |
+ else both = true | |
+ } | |
+ }) | |
+ | |
+ userB.sendQueryMsg() // must have AKEd for SM | |
+ | |
+ userB.on('smp', function (type) { | |
+ switch (type) { | |
+ case 'question': | |
+ userB.smpSecret('applesAndOranges') | |
+ break | |
+ case 'trust': | |
+ assert.ok(userB.trust, 'Trust A? false') | |
+ if (both) done() | |
+ else both = true | |
+ break | |
+ default: | |
+ throw new Error('should not be here') | |
+ } | |
+ }) | |
+ | |
+ }) | |
+ | |
}) | |
\ No newline at end of file | |
diff --git a/vendor/bigint.js b/vendor/bigint.js | |
index ad2a7ab..fe476d6 100644 | |
--- a/vendor/bigint.js | |
+++ b/vendor/bigint.js | |
@@ -1567,10 +1567,21 @@ | |
, bpe : bpe | |
, primes : primes | |
, findPrimes : findPrimes | |
+ , getSeed : getSeed | |
} | |
- function seedRand(state) { | |
- return function () { | |
+ function seedRand(buf) { | |
+ | |
+ var state = new Salsa20([ | |
+ buf[ 0], buf[ 1], buf[ 2], buf[ 3], buf[ 4], buf[ 5], buf[ 6], buf[ 7], | |
+ buf[ 8], buf[ 9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], | |
+ buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], | |
+ buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31] | |
+ ],[ | |
+ buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39] | |
+ ]) | |
+ | |
+ Math.random = function () { | |
var x, o = '' | |
while (o.length < 16) { | |
x = state.getBytes(1) | |
@@ -1578,10 +1589,10 @@ | |
} | |
return parseFloat('0.' + o) | |
} | |
- } | |
- ;(function seed() { | |
+ } | |
+ function getSeed() { | |
var buf | |
if ( (typeof crypto !== 'undefined') && | |
(typeof crypto.randomBytes === 'function') | |
@@ -1597,20 +1608,15 @@ | |
} else { | |
throw new Error('Keys should not be generated without CSPRNG.') | |
} | |
+ return Array.prototype.slice.call(buf, 0) | |
+ } | |
- var state = new Salsa20([ | |
- buf[ 0], buf[ 1], buf[ 2], buf[ 3], buf[ 4], buf[ 5], buf[ 6], buf[ 7], | |
- buf[ 8], buf[ 9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], | |
- buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], | |
- buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31] | |
- ],[ | |
- buf[32], buf[33], buf[34], buf[35], buf[36], buf[37], buf[38], buf[39] | |
- ]) | |
+ ;(function seed() { | |
- Math.random = seedRand(state) | |
+ seedRand(getSeed()) | |
// reseed every 5 mins | |
- setTimeout(seed, 5 * 60 * 1000) | |
+ if (typeof setTimeout === 'function') setTimeout(seed, 5 * 60 * 1000) | |
}()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment