From a78fa30e940dc530c96f176e2f3573054ad681e5 Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Mon, 11 Nov 2013 18:54:32 -0800 Subject: [PATCH] bump version --- bower.json | 2 +- build/dep/bigint.js | 338 ++++++++++++++++++++++------------------- build/dsa-webworker.js | 52 +++++++ build/otr.js | 218 ++++++++++++-------------- build/otr.min.js | 6 +- build/sm-webworker.js | 60 ++++++++ changelog.md | 11 ++ package.json | 2 +- 8 files changed, 412 insertions(+), 277 deletions(-) create mode 100644 build/dsa-webworker.js create mode 100644 build/sm-webworker.js diff --git a/bower.json b/bower.json index a4531d4..ae6c338 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "otr", - "version": "0.2.7", + "version": "0.2.8", "main": "build/otr.js", "ignore": [ "**/.*", diff --git a/build/dep/bigint.js b/build/dep/bigint.js index e8b5de4..a78562b 100644 --- a/build/dep/bigint.js +++ b/build/dep/bigint.js @@ -1,17 +1,14 @@ ;(function (root, factory) { - var Salsa20, crypto if (typeof define === 'function' && define.amd) { - define(['salsa20'], factory.bind(root, root.crypto)) + define(factory.bind(root, root.crypto || root.msCrypto)) } else if (typeof module !== 'undefined' && module.exports) { - Salsa20 = require('./salsa20.js') - crypto = require('crypto') - module.exports = factory(crypto, Salsa20) + module.exports = factory(require('crypto')) } else { - root.BigInt = factory(root.crypto, root.Salsa20) + root.BigInt = factory(root.crypto || root.msCrypto) } -}(this, function (crypto, Salsa20) { +}(this, function (crypto) { //////////////////////////////////////////////////////////////////////////////////////// // Big Integer Library v. 5.5 @@ -151,7 +148,7 @@ // void linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys // void mont_(x,y,n,np) //Montgomery multiplication (see comments where the function is defined) // void multInt_(x,n) //do x=x*n where x is a bigInt and n is an integer. - // void rightShift_(x,n) //right shift bigInt x by n bits. 0 <= n < bpe. (This never overflows its array). + // void rightShift_(x,n) //right shift bigInt x by n bits. (This never overflows its array). // void squareMod_(x,n) //do x=x*x mod n for bigInts x,n // void subShift_(x,y,ys) //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement. // @@ -195,18 +192,18 @@ //////////////////////////////////////////////////////////////////////////////////////// //globals - var bpe = 0 // bits stored per array element - var mask=0; //AND this with an array element to chop it down to bpe bits - var radix=mask+1; //equals 2^bpe. A single 1 bit to the left of the last bit of mask. + + // The number of significant bits in the fraction of a JavaScript + // floating-point number is 52, independent of platform. + // See: https://github.com/arlolra/otr/issues/41 + + var bpe = 26; // bits stored per array element + var radix = 1 << bpe; // equals 2^bpe + var mask = radix - 1; // AND this with an array element to chop it down to bpe bits //the digits for converting to different bases var digitsStr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-'; - //initialize the global variables - for (bpe = 0; (1<<(bpe+1)) > (1<>=1; // bpe = number of bits in one element of the array representing the bigInt - mask=(1<1 ? y[ky-2] : 0)*q[i-ky]; - c=y2>>bpe; + c=y2; y2=y2 & mask; + c = (c - y2) / radix; y1=c+q[i-ky]*y[ky-1]; - c=y1>>bpe; + c=y1; y1=y1 & mask; + c = (c - y1) / radix; if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i]) q[i-ky]--; @@ -972,11 +971,12 @@ c+=x[i]; b=0; if (c<0) { - b=-(c>>bpe); + b = c & mask; + b = -((c - b) / radix); c+=b*radix; } x[i]=c & mask; - c=(c>>bpe)-b; + c = ((c - x[i]) / radix) - b; } } @@ -1169,16 +1169,17 @@ c+=x[i]; b=0; if (c<0) { - b=-(c>>bpe); + b = c & mask; + b = -((c - b) / radix); c+=b*radix; } x[i]=c & mask; - c=(c>>bpe)-b; + c = ((c - x[i]) / radix) - b; if (!c) return; //stop carrying as soon as the carry is zero } } - //right shift bigInt x by n bits. 0 <= n < bpe. + //right shift bigInt x by n bits. function rightShift_(x,n) { var i; var k=Math.floor(n/bpe); @@ -1235,11 +1236,12 @@ c+=x[i]*n; b=0; if (c<0) { - b=-(c>>bpe); + b = c & mask; + b = -((c - b) / radix); c+=b*radix; } x[i]=c & mask; - c=(c>>bpe)-b; + c = ((c - x[i]) / radix) - b; } } @@ -1263,12 +1265,12 @@ for (c=0,i=0;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;i>=bpe; + c = (c - x[i]) / radix; } } @@ -1281,12 +1283,12 @@ for (c=0,i=ys;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;c && i>=bpe; + c = (c - x[i]) / radix; } } @@ -1299,12 +1301,12 @@ for (c=0,i=ys;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;c && i>=bpe; + c = (c - x[i]) / radix; } } @@ -1317,12 +1319,12 @@ for (c=0,i=ys;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;c && i>=bpe; + c = (c - x[i]) / radix; } } @@ -1335,12 +1337,12 @@ for (c=0,i=0;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;c && i>=bpe; + c = (c - x[i]) / radix; } } @@ -1352,12 +1354,12 @@ for (c=0,i=0;i>=bpe; + c = (c - x[i]) / radix; } for (i=k;c && i>=bpe; + c = (c - x[i]) / radix; } } @@ -1409,11 +1411,11 @@ for (i=0;i>=bpe; + c = (c - s0[2*i]) / radix; for (j=i+1;j>=bpe; + c = (c - s0[i+j]) / radix; } s0[i+kx]=c; } @@ -1497,7 +1499,7 @@ // n is odd // np = -(n^(-1)) mod radix function mont_(x,y,n,np) { - var i,j,c,ui,t,ks; + var i,j,c,ui,t,t2,ks; var kn=n.length; var ky=y.length; @@ -1514,24 +1516,35 @@ for (i=0; i> bpe; + c=(t+ui*n[0]); + c = (c - (c & mask)) / radix; t=x[i]; //do sa=(sa+x[i]*y+ui*n)/b where b=2**bpe. Loop is unrolled 5-fold for speed j=1; - for (;j>=bpe; j++; - c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]+t*y[j]; sa[j-1]=c & mask; c>>=bpe; j++; } - for (;j>=bpe; j++; } - for (;j>=bpe; j++; - c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; - c+=sa[j]+ui*n[j]; sa[j-1]=c & mask; c>>=bpe; j++; } - for (;j>=bpe; j++; } - for (;j>=bpe; j++; } + for (;j "\00" + } + return _num2bin + }()) + + // serialize a bigInt to an ascii string + // padded up to pad length + function bigInt2bits(bi, pad) { + pad || (pad = 0) + bi = dup(bi) + var ba = '' + while (!isZero(bi)) { + ba = _num2bin[bi[0] & 0xff] + ba + rightShift_(bi, 8) + } + while (ba.length < pad) { + ba = '\x00' + ba + } + return ba + } + + // converts a byte array to a bigInt + function ba2bigInt(data) { + var mpi = str2bigInt('0', 10, data.length) + data.forEach(function (d, i) { + if (i) leftShift_(mpi, 8) + mpi[0] |= d + }) + return mpi + } + + // returns a function that returns an array of n bytes + var randomBytes = (function () { + + // in node + if ( typeof crypto !== 'undefined' && + typeof crypto.randomBytes === 'function' ) { + return function (n) { + try { + var buf = crypto.randomBytes(n) + } catch (e) { throw e } + return Array.prototype.slice.call(buf, 0) + } + } + + // in browser + else if ( typeof crypto !== 'undefined' && + typeof crypto.getRandomValues === 'function' ) { + return function (n) { + var buf = new Uint8Array(n) + crypto.getRandomValues(buf) + return Array.prototype.slice.call(buf, 0) + } + } + + // err + else { + throw new Error('Keys should not be generated without CSPRNG.') + } + + }()) + + // Salsa 20 in webworker needs a 40 byte seed + function getSeed() { + return randomBytes(40) + } + + // returns a single random byte + function randomByte() { + return randomBytes(1)[0] + } + + // returns a k-bit random integer + function randomBitInt(k) { + if (k > 31) throw new Error("Too many bits.") + var i = 0, r = 0 + var b = Math.floor(k / 8) + var mask = (1 << (k % 8)) - 1 + if (mask) r = randomByte() & mask + for (; i < b; i++) + r = (256 * r) + randomByte() + return r + } - var BigInt = { + return { str2bigInt : str2bigInt , bigInt2str : bigInt2str , int2bigInt : int2bigInt @@ -1578,103 +1702,11 @@ , primes : primes , findPrimes : findPrimes , getSeed : getSeed + , divMod : divMod + , subMod : subMod + , twoToThe : twoToThe + , bigInt2bits : bigInt2bits + , ba2bigInt : ba2bigInt } - // from http://davidbau.com/encode/seedrandom.js - - var randomBitInt - - 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] - ]) - - var width = 256 - , chunks = 6 - , significance = Math.pow(2, 52) - , overflow = significance * 2 - - function numerator() { - var bytes = state.getBytes(chunks) - var i = 0, r = 0 - for (; i < chunks; i++) { - r = r * width + bytes[i] - } - return r - } - - function randomByte() { - return state.getBytes(1)[0] - } - - randomBitInt = function (k) { - if (k > 31) throw new Error("Too many bits.") - var i = 0, r = 0 - var b = Math.floor(k / 8) - var mask = (1 << (k % 8)) - 1 - if (mask) r = randomByte() & mask - for (; i < b; i++) - r = (256 * r) + randomByte() - return r - } - - // This function returns a random double in [0, 1) that contains - // randomness in every bit of the mantissa of the IEEE 754 value. - - return function () { // Closure to return a random double: - var n = numerator() // Start with a numerator n < 2 ^ 48 - , d = Math.pow(width, chunks) // and denominator d = 2 ^ 48. - , x = 0 // and no 'extra last byte'. - while (n < significance) { // Fill up all significant digits by - n = (n + x) * width // shifting numerator and - d *= width // denominator and generating a - x = randomByte() // new least-significant-byte. - } - while (n >= overflow) { // To avoid rounding up, before adding - n /= 2 // last byte, shift everything - d /= 2 // right using integer math until - x >>>= 1 // we have exactly the desired bits. - } - return (n + x) / d // Form the number within [0, 1). - } - - } - - function getSeed() { - var buf - if ( (typeof crypto !== 'undefined') && - (typeof crypto.randomBytes === 'function') - ) { - try { - buf = crypto.randomBytes(40) - } catch (e) { throw e } - } else if ( (typeof crypto !== 'undefined') && - (typeof crypto.getRandomValues === 'function') - ) { - buf = new Uint8Array(40) - crypto.getRandomValues(buf) - } else { - throw new Error('Keys should not be generated without CSPRNG.') - } - return Array.prototype.slice.call(buf, 0) - } - - ;(function seed() { - - Math.random = seedRand(getSeed()) - - // reseed every 5 mins (not in ww) - if ( typeof setTimeout === 'function' && typeof document !== 'undefined' ) - setTimeout(seed, 5 * 60 * 1000) - - }()) - - return BigInt - })) \ No newline at end of file diff --git a/build/dsa-webworker.js b/build/dsa-webworker.js new file mode 100644 index 0000000..d84ad17 --- /dev/null +++ b/build/dsa-webworker.js @@ -0,0 +1,52 @@ +;(function (root) { + "use strict"; + + root.OTR = {} + root.DSA = {} + root.crypto = { + randomBytes: function () { + throw new Error("Haven't seeded yet.") + } + } + + // default imports + var imports = [ + 'vendor/salsa20.js' + , 'vendor/bigint.js' + , 'vendor/crypto.js' + , 'vendor/eventemitter.js' + , 'lib/const.js' + , 'lib/helpers.js' + , 'lib/dsa.js' + ] + + function sendMsg(type, val) { + postMessage({ type: type, val: val }) + } + + onmessage = function (e) { + var data = e.data; + + if (data.imports) imports = data.imports + importScripts.apply(root, imports); + + // use salsa20 since there's no prng in webworkers + var state = new root.Salsa20(data.seed.slice(0, 32), data.seed.slice(32)) + root.crypto.randomBytes = function (n) { + return state.getBytes(n) + } + + if (data.debug) sendMsg('debug', 'DSA key creation started') + var dsa + try { + dsa = new root.DSA() + } catch (e) { + if (data.debug) sendMsg('debug', e.toString()) + return + } + if (data.debug) sendMsg('debug', 'DSA key creation finished') + + sendMsg('data', dsa.packPrivate()) + } + +}(this)) \ No newline at end of file diff --git a/build/otr.js b/build/otr.js index adc9d5f..49f0916 100644 --- a/build/otr.js +++ b/build/otr.js @@ -1,6 +1,6 @@ /*! - otr.js v0.2.7 - 2013-10-12 + otr.js v0.2.8 - 2013-11-11 (c) 2013 - Arlo Breault Freely distributed under the MPL v2.0 license. @@ -120,6 +120,8 @@ var WRAPPER_BEGIN = "?OTR" , WRAPPER_END = "." + var TWO = BigInt.str2bigInt('2', 10) + HLP.debug = function (msg) { // used as HLP.debug.call(ctx, msg) if ( this.debug && @@ -149,17 +151,6 @@ return result === 0 } - HLP.divMod = function (num, den, n) { - return BigInt.multMod(num, BigInt.inverseMod(den, n), n) - } - - HLP.subMod = function (one, two, n) { - one = BigInt.mod(one, n) - two = BigInt.mod(two, n) - if (BigInt.greater(two, one)) one = BigInt.add(one, n) - return BigInt.sub(one, two) - } - HLP.randomExponent = function () { return BigInt.randBigInt(1536) } @@ -231,30 +222,10 @@ return (BigInt.greater(x, a) && BigInt.greater(b, x)) } - HLP.checkGroup = function (g, N) { - var TWO = BigInt.str2bigInt('2', 10) - var N_MINUS_2 = BigInt.sub(N, TWO) + HLP.checkGroup = function (g, N_MINUS_2) { return HLP.GTOE(g, TWO) && HLP.GTOE(N_MINUS_2, g) } - var OPS = { - 'XOR': function (c, s) { return c ^ s } - , 'OR': function (c, s) { return c | s } - , 'AND': function (c, s) { return c & s } - } - HLP.bigBitWise = function (op, a, b) { - var tf = (a.length > b.length) - , short = tf ? b : a - , long = tf ? a : b - , len = long.length - , c = BigInt.expand(short, len) - , i = 0 - for (; i < len; i++) { - c[i] = OPS[op](c[i], long[i]) - } - return c - } - HLP.h1 = function (b, secbytes) { var sha1 = CryptoJS.algo.SHA1.create() sha1.update(CryptoJS.enc.Latin1.parse(b)) @@ -273,13 +244,7 @@ return bytes.substr(start / 8, n / 8) } - HLP.twotothe = function (m) { - var t = [1 << (m % BigInt.bpe), 0] - var i = 0, b = Math.floor(m / BigInt.bpe) - for (; i < b; i++) t.unshift(0) - return t - } - + var _toString = String.fromCharCode; HLP.packBytes = function (val, bytes) { val = val.toString(16) var nex, res = '' // big-endian, unsigned long @@ -309,10 +274,9 @@ } HLP.unpack = function (arr) { - arr.reverse() var val = 0, i = 0, len = arr.length for (; i < len; i++) { - val += Math.pow(256, i) * arr[i] + val = (val * 256) + arr[i] } return val } @@ -321,27 +285,13 @@ return HLP.packINT(d.length) + d } - HLP.bigInt2bits = function (bi, pad) { - pad || (pad = 0) - bi = BigInt.dup(bi) - var ba = '' - while (!BigInt.isZero(bi)) { - ba = _num2bin[bi[0] & 0xff] + ba - BigInt.rightShift_(bi, 8) - } - while (ba.length < pad) { - ba = '\x00' + ba - } - return ba - } - HLP.bits2bigInt = function (bits) { bits = HLP.toByteArray(bits) - return HLP.retMPI(bits) + return BigInt.ba2bigInt(bits) } HLP.packMPI = function (mpi) { - return HLP.packData(HLP.bigInt2bits(BigInt.trim(mpi, 0))) + return HLP.packData(BigInt.bigInt2bits(BigInt.trim(mpi, 0))) } HLP.packSHORT = function (short) { @@ -367,19 +317,10 @@ return [n, data] } - HLP.retMPI = function (data) { - var mpi = BigInt.str2bigInt('0', 10, data.length) - data.forEach(function (d, i) { - if (i) BigInt.leftShift_(mpi, 8) - mpi[0] |= d - }) - return mpi - } - HLP.readMPI = function (data) { data = HLP.toByteArray(data) data = HLP.readData(data) - return HLP.retMPI(data[1]) + return BigInt.ba2bigInt(data[1]) } HLP.packMPIs = function (arr) { @@ -453,41 +394,34 @@ // https://github.com/msgpack/msgpack-javascript/blob/master/msgpack.js - var _bin2num = {} - , _num2bin = {} - , _toString = String.fromCharCode - - var i = 0, v - - for (; i < 0x100; ++i) { - v = _toString(i) - _bin2num[v] = i // "\00" -> 0x00 - _num2bin[i] = v // 0 -> "\00" - } - - for (i = 0x80; i < 0x100; ++i) { // [Webkit][Gecko] - _bin2num[_toString(0xf700 + i)] = i // "\f780" -> 0x80 - } + var _bin2num = (function () { + var i = 0, _bin2num = {} + for (; i < 0x100; ++i) { + _bin2num[String.fromCharCode(i)] = i // "\00" -> 0x00 + } + for (i = 0x80; i < 0x100; ++i) { // [Webkit][Gecko] + _bin2num[String.fromCharCode(0xf700 + i)] = i // "\f780" -> 0x80 + } + return _bin2num + }()) HLP.toByteArray = function (data) { - var rv = [], bin2num = _bin2num, remain + var rv = [] , ary = data.split("") , i = -1 - , iz - - iz = ary.length - remain = iz % 8 + , iz = ary.length + , remain = iz % 8 while (remain--) { ++i - rv[i] = bin2num[ary[i]] + rv[i] = _bin2num[ary[i]] } remain = iz >> 3 while (remain--) { - rv.push(bin2num[ary[++i]], bin2num[ary[++i]], - bin2num[ary[++i]], bin2num[ary[++i]], - bin2num[ary[++i]], bin2num[ary[++i]], - bin2num[ary[++i]], bin2num[ary[++i]]) + rv.push(_bin2num[ary[++i]], _bin2num[ary[++i]], + _bin2num[ary[++i]], _bin2num[ary[++i]], + _bin2num[ary[++i]], _bin2num[ary[++i]], + _bin2num[ary[++i]], _bin2num[ary[++i]]) } return rv } @@ -498,11 +432,12 @@ var root = this - var CryptoJS, BigInt, HLP + var CryptoJS, BigInt, Worker, WWPath, HLP if (typeof module !== 'undefined' && module.exports) { module.exports = DSA CryptoJS = require('../vendor/crypto.js') BigInt = require('../vendor/bigint.js') + WWPath = require('path').join(__dirname, '/dsa-webworker.js') HLP = require('./helpers.js') } else { // copy over and expose internals @@ -512,6 +447,8 @@ root.DSA = DSA CryptoJS = root.CryptoJS BigInt = root.BigInt + Worker = root.Worker + WWPath = 'dsa-webworker.js' HLP = DSA.HLP } @@ -585,7 +522,7 @@ var N = bit_lengths[bit_length].N - var LM1 = HLP.twotothe(bit_length - 1) + var LM1 = BigInt.twoToThe(bit_length - 1) var bl4 = 4 * bit_length var brk = false @@ -701,8 +638,8 @@ // http://www.imperialviolet.org/2013/06/15/suddendeathentropy.html generateNonce: function (m) { - var priv = HLP.bigInt2bits(BigInt.trim(this.x, 0)) - var rand = HLP.bigInt2bits(BigInt.randBigInt(256)) + var priv = BigInt.bigInt2bits(BigInt.trim(this.x, 0)) + var rand = BigInt.bigInt2bits(BigInt.randBigInt(256)) var sha256 = CryptoJS.algo.SHA256.create() sha256.update(CryptoJS.enc.Latin1.parse(priv)) @@ -857,6 +794,43 @@ return BigInt.equals(v, r) } + DSA.createInWebWorker = function (options, cb) { + var opts = { + path: WWPath + , seed: BigInt.getSeed + } + if (options && typeof options === 'object') + Object.keys(options).forEach(function (k) { + opts[k] = options[k] + }) + + // load optional dep. in node + if (typeof module !== 'undefined' && module.exports) + Worker = require('webworker-threads').Worker + + var worker = new Worker(opts.path) + worker.onmessage = function (e) { + var data = e.data + switch (data.type) { + case "debug": + if (!DEBUG || typeof console === 'undefined') return + console.log(data.val) + break; + case "data": + worker.terminate() + cb(DSA.parsePrivate(data.val)) + break; + default: + throw new Error("Unrecognized type.") + } + } + worker.postMessage({ + seed: opts.seed() + , imports: opts.imports + , debug: DEBUG + }) + } + }).call(this) ;(function () { "use strict"; @@ -1089,6 +1063,7 @@ // diffie-hellman modulus // see group 5, RFC 3526 var N = BigInt.str2bigInt(CONST.N, 16) + var N_MINUS_2 = BigInt.sub(N, BigInt.str2bigInt('2', 10)) function hMac(gx, gy, pk, kid, m) { var pass = CryptoJS.enc.Latin1.parse(m) @@ -1174,8 +1149,8 @@ var m = hMac(this.our_dh.publicKey, their_y, pk, kid, m1) m = this.priv.sign(m) var msg = pk + kid - msg += HLP.bigInt2bits(m[0], 20) // pad to 20 bytes - msg += HLP.bigInt2bits(m[1], 20) + msg += BigInt.bigInt2bits(m[0], 20) // pad to 20 bytes + msg += BigInt.bigInt2bits(m[1], 20) msg = CryptoJS.enc.Latin1.parse(msg) var aesctr = HLP.packData(HLP.encryptAes(msg, c, HLP.packCtr(0))) var mac = HLP.makeMac(aesctr, m2) @@ -1290,7 +1265,7 @@ this.their_y = HLP.readMPI(msg[0]) // verify gy is legal 2 <= gy <= N-2 - if (!HLP.checkGroup(this.their_y, N)) + if (!HLP.checkGroup(this.their_y, N_MINUS_2)) return this.otr.error('Illegal g^y.', true) this.createKeys(this.their_y) @@ -1330,7 +1305,7 @@ return this.otr.error('Hashed g^x does not match.', true) // verify gx is legal 2 <= g^x <= N-2 - if (!HLP.checkGroup(this.their_y, N)) + if (!HLP.checkGroup(this.their_y, N_MINUS_2)) return this.otr.error('Illegal g^x.', true) this.createKeys(this.their_y) @@ -1487,6 +1462,7 @@ // see group 5, RFC 3526 var G = BigInt.str2bigInt(CONST.G, 10) var N = BigInt.str2bigInt(CONST.N, 16) + var N_MINUS_2 = BigInt.sub(N, BigInt.str2bigInt('2', 10)) // to calculate D's for zero-knowledge proofs var Q = BigInt.sub(N, BigInt.str2bigInt('1', 10)) @@ -1533,8 +1509,8 @@ this.a3 = HLP.randomExponent() this.g2a = BigInt.powMod(G, this.a2, N) this.g3a = BigInt.powMod(G, this.a3, N) - if ( !HLP.checkGroup(this.g2a, N) || - !HLP.checkGroup(this.g3a, N) + if ( !HLP.checkGroup(this.g2a, N_MINUS_2) || + !HLP.checkGroup(this.g3a, N_MINUS_2) ) this.makeG2s() } @@ -1561,7 +1537,7 @@ } SM.prototype.computeD = function (r, a, c) { - return HLP.subMod(r, BigInt.multMod(a, c, Q), Q) + return BigInt.subMod(r, BigInt.multMod(a, c, Q), Q) } // the bulk of the work @@ -1604,8 +1580,8 @@ if (ms !== 6) return this.abort() msg = HLP.unpackMPIs(6, msg.msg.substring(4)) - if ( !HLP.checkGroup(msg[0], N) || - !HLP.checkGroup(msg[3], N) + if ( !HLP.checkGroup(msg[0], N_MINUS_2) || + !HLP.checkGroup(msg[3], N_MINUS_2) ) return this.abort() // verify znp's @@ -1644,10 +1620,10 @@ if (ms !== 11) return this.abort() msg = HLP.unpackMPIs(11, msg.msg.substring(4)) - if ( !HLP.checkGroup(msg[0], N) || - !HLP.checkGroup(msg[3], N) || - !HLP.checkGroup(msg[6], N) || - !HLP.checkGroup(msg[7], N) + if ( !HLP.checkGroup(msg[0], N_MINUS_2) || + !HLP.checkGroup(msg[3], N_MINUS_2) || + !HLP.checkGroup(msg[6], N_MINUS_2) || + !HLP.checkGroup(msg[7], N_MINUS_2) ) return this.abort() // verify znp of c3 / c3 @@ -1682,8 +1658,8 @@ var d6 = this.computeD(r6, this.secret, cP) // store these - this.QoQ = HLP.divMod(this.q, msg[7], N) - this.PoP = HLP.divMod(this.p, msg[6], N) + this.QoQ = BigInt.divMod(this.q, msg[7], N) + this.PoP = BigInt.divMod(this.p, msg[6], N) this.computeR() @@ -1719,9 +1695,9 @@ if (ms !== 8) return this.abort() msg = HLP.unpackMPIs(8, msg.msg.substring(4)) - if ( !HLP.checkGroup(msg[0], N) || - !HLP.checkGroup(msg[1], N) || - !HLP.checkGroup(msg[5], N) + if ( !HLP.checkGroup(msg[0], N_MINUS_2) || + !HLP.checkGroup(msg[1], N_MINUS_2) || + !HLP.checkGroup(msg[5], N_MINUS_2) ) return this.abort() // verify znp of cP @@ -1734,7 +1710,7 @@ // verify znp of cR t3 = HLP.multPowMod(G, msg[7], this.g3ao, msg[6], N) - this.QoQ = HLP.divMod(msg[1], this.q, N) // save Q over Q + this.QoQ = BigInt.divMod(msg[1], this.q, N) // save Q over Q t4 = HLP.multPowMod(this.QoQ, msg[7], msg[5], msg[6], N) if (!HLP.ZKP(7, msg[6], t3, t4)) @@ -1753,7 +1729,7 @@ send = HLP.packTLV(5, send) rab = this.computeRab(msg[5]) - trust = !!BigInt.equals(rab, HLP.divMod(msg[0], this.p, N)) + trust = !!BigInt.equals(rab, BigInt.divMod(msg[0], this.p, N)) this.trigger('trust', [trust, 'answered']) this.init() @@ -1767,7 +1743,7 @@ if (ms !== 3) return this.abort() msg = HLP.unpackMPIs(3, msg.msg.substring(4)) - if (!HLP.checkGroup(msg[0], N)) return this.abort() + if (!HLP.checkGroup(msg[0], N_MINUS_2)) return this.abort() // verify znp of cR t3 = HLP.multPowMod(G, msg[2], this.g3ao, msg[1], N) @@ -1901,7 +1877,6 @@ CryptoJS = require('../vendor/crypto.js') BigInt = require('../vendor/bigint.js') EventEmitter = require('../vendor/eventemitter.js') - Worker = require('webworker-threads').Worker SMWPath = require('path').join(__dirname, '/sm-webworker.js') CONST = require('./const.js') HLP = require('./helpers.js') @@ -2052,6 +2027,11 @@ Object.keys(otr.smw).forEach(function (k) { opts[k] = otr.smw[k] }) + + // load optional dep. in node + if (typeof module !== 'undefined' && module.exports) + Worker = require('webworker-threads').Worker + this.worker = new Worker(opts.path) var self = this this.worker.onmessage = function (e) { diff --git a/build/otr.min.js b/build/otr.min.js index 3519b43..bc3b24a 100644 --- a/build/otr.min.js +++ b/build/otr.min.js @@ -1,6 +1,6 @@ /*! - otr.js v0.2.7 - 2013-10-12 + otr.js v0.2.8 - 2013-11-11 (c) 2013 - Arlo Breault Freely distributed under the MPL v2.0 license. @@ -9,5 +9,5 @@ */ -!function(root,factory){"function"==typeof define&&define.amd?define(["bigint","crypto","eventemitter"],function(BigInt,CryptoJS,EventEmitter){var root={BigInt:BigInt,CryptoJS:CryptoJS,EventEmitter:EventEmitter,OTR:{},DSA:{}};return factory.call(root)}):(root.OTR={},root.DSA={},factory.call(root))}(this,function(){return function(){"use strict";var root=this,CONST={N:"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",G:"2",MSGSTATE_PLAINTEXT:0,MSGSTATE_ENCRYPTED:1,MSGSTATE_FINISHED:2,AUTHSTATE_NONE:0,AUTHSTATE_AWAITING_DHKEY:1,AUTHSTATE_AWAITING_REVEALSIG:2,AUTHSTATE_AWAITING_SIG:3,WHITESPACE_TAG:" ",WHITESPACE_TAG_V2:" ",WHITESPACE_TAG_V3:" ",OTR_TAG:"?OTR",OTR_VERSION_1:"\0",OTR_VERSION_2:"\0",OTR_VERSION_3:"\0",SMPSTATE_EXPECT0:0,SMPSTATE_EXPECT1:1,SMPSTATE_EXPECT2:2,SMPSTATE_EXPECT3:3,SMPSTATE_EXPECT4:4,STATUS_SEND_QUERY:0,STATUS_AKE_INIT:1,STATUS_AKE_SUCCESS:2,STATUS_END_OTR:3};"undefined"!=typeof module&&module.exports?module.exports=CONST:root.OTR.CONST=CONST}.call(this),function(){"use strict";var CryptoJS,BigInt,root=this,HLP={};"undefined"!=typeof module&&module.exports?(module.exports=HLP={},CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js")):(root.OTR&&(root.OTR.HLP=HLP),root.DSA&&(root.DSA.HLP=HLP),CryptoJS=root.CryptoJS,BigInt=root.BigInt);var DTS={BYTE:1,SHORT:2,INT:4,CTR:8,MAC:20,SIG:40},WRAPPER_BEGIN="?OTR",WRAPPER_END=".";HLP.debug=function(msg){this.debug&&"function"!=typeof this.debug&&"undefined"!=typeof console&&console.log(msg)},HLP.extend=function(child,parent){function Ctor(){this.constructor=child}for(var key in parent)Object.hasOwnProperty.call(parent,key)&&(child[key]=parent[key]);Ctor.prototype=parent.prototype,child.prototype=new Ctor,child.__super__=parent.prototype},HLP.compare=function(str1,str2){if(str1.length!==str2.length)return!1;for(var i=0,result=0;ib.length,short=tf?b:a,long=tf?a:b,len=long.length,c=BigInt.expand(short,len),i=0;len>i;i++)c[i]=OPS[op](c[i],long[i]);return c},HLP.h1=function(b,secbytes){var sha1=CryptoJS.algo.SHA1.create();return sha1.update(CryptoJS.enc.Latin1.parse(b)),sha1.update(CryptoJS.enc.Latin1.parse(secbytes)),sha1.finalize().toString(CryptoJS.enc.Latin1)},HLP.h2=function(b,secbytes){var sha256=CryptoJS.algo.SHA256.create();return sha256.update(CryptoJS.enc.Latin1.parse(b)),sha256.update(CryptoJS.enc.Latin1.parse(secbytes)),sha256.finalize().toString(CryptoJS.enc.Latin1)},HLP.mask=function(bytes,start,n){return bytes.substr(start/8,n/8)},HLP.twotothe=function(m){for(var t=[1<i;i++)t.unshift(0);return t},HLP.packBytes=function(val,bytes){val=val.toString(16);for(var nex,res="";bytes>0;bytes--)nex=val.length?val.substr(-2,2):"0",val=val.substr(0,val.length-2),res=_toString(parseInt(nex,16))+res;return res},HLP.packINT=function(d){return HLP.packBytes(d,DTS.INT)},HLP.packCtr=function(d){return HLP.padCtr(HLP.packBytes(d,DTS.CTR))},HLP.padCtr=function(ctr){return ctr+"\0\0\0\0\0\0\0\0"},HLP.unpackCtr=function(d){return d=HLP.toByteArray(d.substring(0,8)),HLP.unpack(d)},HLP.unpack=function(arr){arr.reverse();for(var val=0,i=0,len=arr.length;len>i;i++)val+=Math.pow(256,i)*arr[i];return val},HLP.packData=function(d){return HLP.packINT(d.length)+d},HLP.bigInt2bits=function(bi,pad){pad||(pad=0),bi=BigInt.dup(bi);for(var ba="";!BigInt.isZero(bi);)ba=_num2bin[255&bi[0]]+ba,BigInt.rightShift_(bi,8);for(;ba.lengthi;i++)arr.push("MPI");return HLP.splitype(arr,mpis).map(function(m){return HLP.readMPI(m)})},HLP.wrapMsg=function(msg,fs,v3,our_it,their_it){msg=CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg)),msg=WRAPPER_BEGIN+":"+msg+WRAPPER_END;var its;if(v3&&(its="|",its+=HLP.readLen(our_it).toString(16),its+="|",its+=HLP.readLen(their_it).toString(16)),!fs)return[null,msg];var n=Math.ceil(msg.length/fs);if(n>65535)return["Too many fragments"];if(1==n)return[null,msg];var k,bi,ei,frag,mf,mfs=[];for(k=1;n>=k;k++)bi=(k-1)*fs,ei=k*fs,frag=msg.slice(bi,ei),mf=WRAPPER_BEGIN,v3&&(mf+=its),mf+=","+k+",",mf+=n+",",mf+=frag+",",mfs.push(mf);return[null,mfs]},HLP.splitype=function splitype(arr,msg){var data=[];return arr.forEach(function(a){var str;switch(a){case"PUBKEY":str=splitype(["SHORT","MPI","MPI","MPI","MPI"],msg).join("");break;case"DATA":case"MPI":str=msg.substring(0,HLP.readLen(msg)+4);break;default:str=msg.substring(0,DTS[a])}data.push(str),msg=msg.substring(str.length)}),data};for(var v,_bin2num={},_num2bin={},_toString=String.fromCharCode,i=0;256>i;++i)v=_toString(i),_bin2num[v]=i,_num2bin[i]=v;for(i=128;256>i;++i)_bin2num[_toString(63232+i)]=i;HLP.toByteArray=function(data){var remain,iz,rv=[],bin2num=_bin2num,ary=data.split(""),i=-1;for(iz=ary.length,remain=iz%8;remain--;)++i,rv[i]=bin2num[ary[i]];for(remain=iz>>3;remain--;)rv.push(bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]],bin2num[ary[++i]]);return rv}}.call(this),function(){"use strict";function timer(){var start=(new Date).getTime();return function(s){if(DEBUG&&"undefined"!=typeof console){var t=(new Date).getTime();console.log(s+": "+(t-start)),start=t}}}function makeRandom(min,max){var c=BigInt.randBigInt(BigInt.bitSize(max));return HLP.between(c,min,max)?c:makeRandom(min,max)}function isProbPrime(k,n){var i,B=3e4,l=BigInt.bitSize(k),primes=BigInt.primes;for(0===primes.length&&(primes=BigInt.findPrimes(B)),rpprb.length!=k.length&&(rpprb=BigInt.dup(k)),i=0;ii;i++){for(BigInt.randBigInt_(rpprb,l,0);!BigInt.greater(k,rpprb);)BigInt.randBigInt_(rpprb,l,0);if(!BigInt.millerRabin(k,rpprb))return 0}return 1}function generatePrimes(bit_length){for(var q,p,rem,counter,t=timer(),repeat=bit_lengths[bit_length].repeat,N=bit_lengths[bit_length].N,LM1=HLP.twotothe(bit_length-1),bl4=4*bit_length,brk=!1;;)if(q=BigInt.randBigInt(N,1),q[0]|=1,isProbPrime(q,repeat)){for(t("q"),counter=0;bl4>counter;counter++)if(p=BigInt.randBigInt(bit_length,1),p[0]|=1,rem=BigInt.mod(p,q),rem=BigInt.sub(rem,ONE),p=BigInt.sub(p,rem),!BigInt.greater(LM1,p)&&isProbPrime(p,repeat)){t("p"),primes[bit_length]={p:p,q:q},brk=!0;break}if(brk)break}for(var g,h=BigInt.dup(TWO),pm1=BigInt.sub(p,ONE),e=BigInt.multMod(pm1,BigInt.inverseMod(q,p),p);;){g=BigInt.powMod(h,e,p);{if(!BigInt.equals(g,ONE))return primes[bit_length].g=g,t("g"),void 0;h=BigInt.add(h,ONE)}}throw new Error("Unreachable!")}function DSA(obj,opts){if(!(this instanceof DSA))return new DSA(obj,opts);if(opts=opts||{},obj){var self=this;return["p","q","g","y","x"].forEach(function(prop){self[prop]=obj[prop]}),this.type=obj.type||KEY_TYPE,void 0}var bit_length=parseInt(opts.bit_length?opts.bit_length:1024,10);if(!bit_lengths[bit_length])throw new Error("Unsupported bit length.");primes[bit_length]||generatePrimes(bit_length),this.p=primes[bit_length].p,this.q=primes[bit_length].q,this.g=primes[bit_length].g,this.type=KEY_TYPE,this.x=makeRandom(ZERO,this.q),this.y=BigInt.powMod(this.g,this.x,this.p),opts.nocache&&(primes[bit_length]=null)}function tokenizeStr(str){var start,end;if(start=str.indexOf("("),end=str.lastIndexOf(")"),0>start||0>end)throw new Error("Malformed S-Expression");str=str.substring(start+1,end);var splt=str.search(/\s/),obj={type:str.substring(0,splt),val:[]};if(str=str.substring(splt+1,end),start=str.indexOf("("),0>start)obj.val.push(str);else for(var i,len,ss,es;start>-1;){for(i=start+1,len=str.length,ss=1,es=0;len>i&&ss>es;i++)"("===str[i]&&ss++,")"===str[i]&&es++;obj.val.push(tokenizeStr(str.substring(start,++i))),str=str.substring(++i),start=str.indexOf("(")}return obj}function parseLibotr(obj){if(!obj.type)throw new Error("Parse error.");var o,val;return"privkeys"===obj.type?(o=[],obj.val.forEach(function(i){o.push(parseLibotr(i))}),o):(o={},obj.val.forEach(function(i){val=i.val[0],"string"==typeof val?0===val.indexOf("#")&&(val=val.substring(1,val.lastIndexOf("#")),val=BigInt.str2bigInt(val,16)):val=parseLibotr(i),o[i.type]=val}),o)}var CryptoJS,BigInt,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=DSA,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),HLP=require("./helpers.js")):(Object.keys(root.DSA).forEach(function(k){DSA[k]=root.DSA[k]}),root.DSA=DSA,CryptoJS=root.CryptoJS,BigInt=root.BigInt,HLP=DSA.HLP);var ZERO=BigInt.str2bigInt("0",10),ONE=BigInt.str2bigInt("1",10),TWO=BigInt.str2bigInt("2",10),KEY_TYPE="\0\0",DEBUG=!1,rpprb=[],bit_lengths={1024:{N:160,repeat:40},2048:{N:224,repeat:56}},primes={};DSA.prototype={constructor:DSA,packPublic:function(){var str=this.type;return str+=HLP.packMPI(this.p),str+=HLP.packMPI(this.q),str+=HLP.packMPI(this.g),str+=HLP.packMPI(this.y)},packPrivate:function(){var str=this.packPublic()+HLP.packMPI(this.x);return str=CryptoJS.enc.Latin1.parse(str),str.toString(CryptoJS.enc.Base64)},generateNonce:function(m){var priv=HLP.bigInt2bits(BigInt.trim(this.x,0)),rand=HLP.bigInt2bits(BigInt.randBigInt(256)),sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(priv)),sha256.update(m),sha256.update(CryptoJS.enc.Latin1.parse(rand));var hash=sha256.finalize();return hash=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1)),BigInt.rightShift_(hash,256-BigInt.bitSize(this.q)),HLP.between(hash,ZERO,this.q)?hash:this.generateNonce(m)},sign:function(m){m=CryptoJS.enc.Latin1.parse(m);for(var k,b=BigInt.str2bigInt(m.toString(CryptoJS.enc.Hex),16),r=ZERO,s=ZERO;BigInt.isZero(s)||BigInt.isZero(r);)k=this.generateNonce(m),r=BigInt.mod(BigInt.powMod(this.g,k,this.p),this.q),BigInt.isZero(r)||(s=BigInt.inverseMod(k,this.q),s=BigInt.mult(s,BigInt.add(b,BigInt.mult(this.x,r))),s=BigInt.mod(s,this.q));return[r,s]},fingerprint:function(){var pk=this.packPublic();return this.type===KEY_TYPE&&(pk=pk.substring(2)),pk=CryptoJS.enc.Latin1.parse(pk),CryptoJS.SHA1(pk).toString(CryptoJS.enc.Hex)}},DSA.parsePublic=function(str,priv){var fields=["SHORT","MPI","MPI","MPI","MPI"];priv&&fields.push("MPI"),str=HLP.splitype(fields,str);var obj={type:str[0],p:HLP.readMPI(str[1]),q:HLP.readMPI(str[2]),g:HLP.readMPI(str[3]),y:HLP.readMPI(str[4])};return priv&&(obj.x=HLP.readMPI(str[5])),new DSA(obj)},DSA.parsePrivate=function(str,libotr){return libotr?parseLibotr(tokenizeStr(str))[0]["private-key"].dsa:(str=CryptoJS.enc.Base64.parse(str),str=str.toString(CryptoJS.enc.Latin1),DSA.parsePublic(str,!0))},DSA.verify=function(key,m,r,s){if(!HLP.between(r,ZERO,key.q)||!HLP.between(s,ZERO,key.q))return!1;var hm=CryptoJS.enc.Latin1.parse(m);hm=BigInt.str2bigInt(hm.toString(CryptoJS.enc.Hex),16);var w=BigInt.inverseMod(s,key.q),u1=BigInt.multMod(hm,w,key.q),u2=BigInt.multMod(r,w,key.q);u1=BigInt.powMod(key.g,u1,key.p),u2=BigInt.powMod(key.y,u2,key.p);var v=BigInt.mod(BigInt.multMod(u1,u2,key.p),key.q);return BigInt.equals(v,r)}}.call(this),function(){"use strict";var CryptoJS,CONST,HLP,root=this,Parse={};"undefined"!=typeof module&&module.exports?(module.exports=Parse,CryptoJS=require("../vendor/crypto.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.Parse=Parse,CryptoJS=root.CryptoJS,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var tags={};tags[CONST.WHITESPACE_TAG_V2]=CONST.OTR_VERSION_2,tags[CONST.WHITESPACE_TAG_V3]=CONST.OTR_VERSION_3,Parse.parseMsg=function(otr,msg){var ver=[],start=msg.indexOf(CONST.OTR_TAG);if(!~start){if(this.initFragment(otr),ind=msg.indexOf(CONST.WHITESPACE_TAG),~ind){msg=msg.split(""),msg.splice(ind,16);for(var tag,len=msg.length;len>ind;)tag=msg.slice(ind,ind+8).join(""),Object.hasOwnProperty.call(tags,tag)?(msg.splice(ind,8),ver.push(tags[tag])):ind+=8;msg=msg.join("")}return{msg:msg,ver:ver}}var ind=start+CONST.OTR_TAG.length,com=msg[ind];if(","===com||"|"===com)return this.msgFragment(otr,msg.substring(ind+1),"|"===com);if(this.initFragment(otr),~["?","v"].indexOf(com)){"?"===msg[ind]&&(ver.push(CONST.OTR_VERSION_1),ind+=1);var vers={2:CONST.OTR_VERSION_2,3:CONST.OTR_VERSION_3},qs=msg.substring(ind+1),qi=qs.indexOf("?");return qi>=1&&(qs=qs.substring(0,qi).split(""),"v"===msg[ind]&&qs.forEach(function(q){Object.hasOwnProperty.call(vers,q)&&ver.push(vers[q])})),{cls:"query",ver:ver}}if(":"===com){ind+=1;var info=msg.substring(ind,ind+4);if(info.length<4)return{msg:msg};info=CryptoJS.enc.Base64.parse(info).toString(CryptoJS.enc.Latin1);var version=info.substring(0,2),type=info.substring(2);if(!otr["ALLOW_V"+HLP.unpackSHORT(version)])return{msg:msg};ind+=4;var end=msg.substring(ind).indexOf(".");if(!~end)return{msg:msg};msg=CryptoJS.enc.Base64.parse(msg.substring(ind,ind+end)),msg=CryptoJS.enc.Latin1.stringify(msg);var instance_tags;version===CONST.OTR_VERSION_3&&(instance_tags=msg.substring(0,8),msg=msg.substring(8));var cls;return~["","\n","",""].indexOf(type)?cls="ake":""===type&&(cls="data"),{version:version,type:type,msg:msg,cls:cls,instance_tags:instance_tags}}return" Error:"===msg.substring(ind,ind+7)?(otr.ERROR_START_AKE&&otr.sendQueryMsg(),{msg:msg.substring(ind+7),cls:"error"}):{msg:msg}},Parse.initFragment=function(otr){otr.fragment={s:"",j:0,k:0}},Parse.msgFragment=function(otr,msg,v3){if(msg=msg.split(","),v3){var its=msg.shift().split("|"),their_it=HLP.packINT(parseInt(its[0],16)),our_it=HLP.packINT(parseInt(its[1],16));if(otr.checkInstanceTags(their_it+our_it))return}if(!(msg.length<4||isNaN(parseInt(msg[0],10))||isNaN(parseInt(msg[1],10)))){var k=parseInt(msg[0],10),n=parseInt(msg[1],10);return msg=msg[2],k>n||0===n||0===k?(this.initFragment(otr),void 0):(1===k?(this.initFragment(otr),otr.fragment={k:1,n:n,s:msg}):n===otr.fragment.n&&k===otr.fragment.k+1?(otr.fragment.s+=msg,otr.fragment.k+=1):this.initFragment(otr),n===k?(msg=otr.fragment.s,this.initFragment(otr),this.parseMsg(otr,msg)):void 0)}}}.call(this),function(){"use strict";function hMac(gx,gy,pk,kid,m){var pass=CryptoJS.enc.Latin1.parse(m),hmac=CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256,pass);return hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gx))),hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gy))),hmac.update(CryptoJS.enc.Latin1.parse(pk)),hmac.update(CryptoJS.enc.Latin1.parse(kid)),hmac.finalize().toString(CryptoJS.enc.Latin1)}function AKE(otr){if(!(this instanceof AKE))return new AKE(otr);this.otr=otr,this.our_dh=otr.our_old_dh,this.our_keyid=otr.our_keyid-1,this.their_y=null,this.their_keyid=null,this.their_priv_pk=null,this.ssid=null,this.transmittedRS=!1,this.r=null,this.priv=otr.priv;var self=this;["sendMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)})}var CryptoJS,BigInt,CONST,HLP,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=AKE,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),CONST=require("./const.js"),HLP=require("./helpers.js"),DSA=require("./dsa.js")):(root.OTR.AKE=AKE,CryptoJS=root.CryptoJS,BigInt=root.BigInt,CONST=root.OTR.CONST,HLP=root.OTR.HLP,DSA=root.DSA);var N=BigInt.str2bigInt(CONST.N,16);AKE.prototype={constructor:AKE,createKeys:function(g){var s=BigInt.powMod(g,this.our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.ssid=HLP.mask(HLP.h2("\0",secbytes),0,64);var tmp=HLP.h2("",secbytes);this.c=HLP.mask(tmp,0,128),this.c_prime=HLP.mask(tmp,128,128),this.m1=HLP.h2("",secbytes),this.m2=HLP.h2("",secbytes),this.m1_prime=HLP.h2("",secbytes),this.m2_prime=HLP.h2("",secbytes)},verifySignMac:function(mac,aesctr,m2,c,their_y,our_dh_pk,m1,ctr){var vmac=HLP.makeMac(aesctr,m2);if(!HLP.compare(mac,vmac))return["MACs do not match."];var x=HLP.decryptAes(aesctr.substring(4),c,ctr);x=HLP.splitype(["PUBKEY","INT","SIG"],x.toString(CryptoJS.enc.Latin1));var m=hMac(their_y,our_dh_pk,x[0],x[1],m1),pub=DSA.parsePublic(x[0]),r=HLP.bits2bigInt(x[2].substring(0,20)),s=HLP.bits2bigInt(x[2].substring(20));return DSA.verify(pub,m,r,s)?[null,HLP.readLen(x[1]),pub]:["Cannot verify signature of m."]},makeM:function(their_y,m1,c,m2){var pk=this.priv.packPublic(),kid=HLP.packINT(this.our_keyid),m=hMac(this.our_dh.publicKey,their_y,pk,kid,m1);m=this.priv.sign(m);var msg=pk+kid;msg+=HLP.bigInt2bits(m[0],20),msg+=HLP.bigInt2bits(m[1],20),msg=CryptoJS.enc.Latin1.parse(msg);var aesctr=HLP.packData(HLP.encryptAes(msg,c,HLP.packCtr(0))),mac=HLP.makeMac(aesctr,m2);return aesctr+mac},akeSuccess:function(version){return HLP.debug.call(this.otr,"success"),BigInt.equals(this.their_y,this.our_dh.publicKey)?this.otr.error("equal keys - we have a problem.",!0):(this.their_keyid!==this.otr.their_keyid&&this.their_keyid!==this.otr.their_keyid-1&&(this.otr.our_old_dh=this.our_dh,this.otr.their_y=this.their_y,this.otr.their_old_y=null,this.otr.their_keyid=this.their_keyid,this.otr.their_priv_pk=this.their_priv_pk,this.otr.sessKeys[0]=[new this.otr.DHSession(this.otr.our_dh,this.otr.their_y),null],this.otr.sessKeys[1]=[new this.otr.DHSession(this.otr.our_old_dh,this.otr.their_y),null]),this.otr.ssid=this.ssid,this.otr.transmittedRS=this.transmittedRS,this.otr_version=version,this.otr.authstate=CONST.AUTHSTATE_NONE,this.otr.msgstate=CONST.MSGSTATE_ENCRYPTED,this.r=null,this.myhashed=null,this.dhcommit=null,this.encrypted=null,this.hashed=null,this.otr.trigger("status",[CONST.STATUS_AKE_SUCCESS]),this.otr.sendStored(),void 0)},handleAKE:function(msg){var send,vsm,type,version=msg.version;switch(msg.type){case"":if(HLP.debug.call(this.otr,"d-h key message"),msg=HLP.splitype(["DATA","DATA"],msg.msg),this.otr.authstate===CONST.AUTHSTATE_AWAITING_DHKEY){var ourHash=HLP.readMPI(this.myhashed),theirHash=HLP.readMPI(msg[1]);if(BigInt.greater(ourHash,theirHash)){type="",send=this.dhcommit;break}this.our_dh=this.otr.dh(),this.otr.authstate=CONST.AUTHSTATE_NONE,this.r=null,this.myhashed=null}else this.otr.authstate===CONST.AUTHSTATE_AWAITING_SIG&&(this.our_dh=this.otr.dh());this.otr.authstate=CONST.AUTHSTATE_AWAITING_REVEALSIG,this.encrypted=msg[0].substring(4),this.hashed=msg[1].substring(4),type="\n",send=HLP.packMPI(this.our_dh.publicKey);break;case"\n":if(HLP.debug.call(this.otr,"reveal signature message"),msg=HLP.splitype(["MPI"],msg.msg),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_DHKEY){if(this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;if(!BigInt.equals(this.their_y,HLP.readMPI(msg[0])))return}if(this.otr.authstate=CONST.AUTHSTATE_AWAITING_SIG,this.their_y=HLP.readMPI(msg[0]),!HLP.checkGroup(this.their_y,N))return this.otr.error("Illegal g^y.",!0);this.createKeys(this.their_y),type="",send=HLP.packMPI(this.r),send+=this.makeM(this.their_y,this.m1,this.c,this.m2),this.m1=null,this.m2=null,this.c=null;break;case"":if(HLP.debug.call(this.otr,"signature message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_REVEALSIG)return;msg=HLP.splitype(["DATA","DATA","MAC"],msg.msg),this.r=HLP.readMPI(msg[0]);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key);var gxmpi=HLP.decryptAes(this.encrypted,key,HLP.packCtr(0));gxmpi=gxmpi.toString(CryptoJS.enc.Latin1),this.their_y=HLP.readMPI(gxmpi);var hash=CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi));return HLP.compare(this.hashed,hash.toString(CryptoJS.enc.Latin1))?HLP.checkGroup(this.their_y,N)?(this.createKeys(this.their_y),vsm=this.verifySignMac(msg[2],msg[1],this.m2,this.c,this.their_y,this.our_dh.publicKey,this.m1,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],send=this.makeM(this.their_y,this.m1_prime,this.c_prime,this.m2_prime),this.m1=null,this.m2=null,this.m1_prime=null,this.m2_prime=null,this.c=null,this.c_prime=null,this.sendMsg(version,"",send),this.akeSuccess(version),void 0)):this.otr.error("Illegal g^x.",!0):this.otr.error("Hashed g^x does not match.",!0);case"":if(HLP.debug.call(this.otr,"data message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;return msg=HLP.splitype(["DATA","MAC"],msg.msg),vsm=this.verifySignMac(msg[1],msg[0],this.m2_prime,this.c_prime,this.their_y,this.our_dh.publicKey,this.m1_prime,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],this.m1_prime=null,this.m2_prime=null,this.c_prime=null,this.transmittedRS=!0,this.akeSuccess(version),void 0);default:return}this.sendMsg(version,type,send)},sendMsg:function(version,type,msg){var send=version+type,v3=version===CONST.OTR_VERSION_3;return v3&&(HLP.debug.call(this.otr,"instance tags"),send+=this.otr.our_instance_tag,send+=this.otr.their_instance_tag),send+=msg,send=HLP.wrapMsg(send,this.otr.fragment_size,v3,this.otr.our_instance_tag,this.otr.their_instance_tag),send[0]?this.otr.error(send[0]):(this.otr._sendMsg(send[1],!0),void 0)},initiateAKE:function(version){HLP.debug.call(this.otr,"d-h commit message"),this.otr.trigger("status",[CONST.STATUS_AKE_INIT]),this.otr.authstate=CONST.AUTHSTATE_AWAITING_DHKEY;var gxmpi=HLP.packMPI(this.our_dh.publicKey);gxmpi=CryptoJS.enc.Latin1.parse(gxmpi),this.r=BigInt.randBigInt(128);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key),this.myhashed=CryptoJS.SHA256(gxmpi),this.myhashed=HLP.packData(this.myhashed.toString(CryptoJS.enc.Latin1)),this.dhcommit=HLP.packData(HLP.encryptAes(gxmpi,key,HLP.packCtr(0))),this.dhcommit+=this.myhashed,this.sendMsg(version,"",this.dhcommit)}}}.call(this),function(){"use strict";function SM(reqs){return this instanceof SM?(this.version=1,this.our_fp=reqs.our_fp,this.their_fp=reqs.their_fp,this.ssid=reqs.ssid,this.debug=!!reqs.debug,this.init(),void 0):new SM(reqs)}var CryptoJS,BigInt,EventEmitter,CONST,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=SM,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.SM=SM,CryptoJS=root.CryptoJS,BigInt=root.BigInt,EventEmitter=root.EventEmitter,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),Q=BigInt.sub(N,BigInt.str2bigInt("1",10));BigInt.divInt_(Q,2),HLP.extend(SM,EventEmitter),SM.prototype.init=function(){this.smpstate=CONST.SMPSTATE_EXPECT1,this.secret=null},SM.prototype.makeSecret=function(our,secret){var sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(this.version,1))),sha256.update(CryptoJS.enc.Hex.parse(our?this.our_fp:this.their_fp)),sha256.update(CryptoJS.enc.Hex.parse(our?this.their_fp:this.our_fp)),sha256.update(CryptoJS.enc.Latin1.parse(this.ssid)),sha256.update(CryptoJS.enc.Latin1.parse(secret));var hash=sha256.finalize();this.secret=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))},SM.prototype.makeG2s=function(){this.a2=HLP.randomExponent(),this.a3=HLP.randomExponent(),this.g2a=BigInt.powMod(G,this.a2,N),this.g3a=BigInt.powMod(G,this.a3,N),HLP.checkGroup(this.g2a,N)&&HLP.checkGroup(this.g3a,N)||this.makeG2s()},SM.prototype.computeGs=function(g2a,g3a){this.g2=BigInt.powMod(g2a,this.a2,N),this.g3=BigInt.powMod(g3a,this.a3,N)},SM.prototype.computePQ=function(r){this.p=BigInt.powMod(this.g3,r,N),this.q=HLP.multPowMod(G,r,this.g2,this.secret,N)},SM.prototype.computeR=function(){this.r=BigInt.powMod(this.QoQ,this.a3,N)},SM.prototype.computeRab=function(r){return BigInt.powMod(r,this.a3,N)},SM.prototype.computeC=function(v,r){return HLP.smpHash(v,BigInt.powMod(G,r,N))},SM.prototype.computeD=function(r,a,c){return HLP.subMod(r,BigInt.multMod(a,c,Q),Q)},SM.prototype.handleSM=function(msg){var send,r2,r3,r7,t1,t2,t3,t4,rab,tmp2,cR,d7,ms,trust,expectStates={2:CONST.SMPSTATE_EXPECT1,3:CONST.SMPSTATE_EXPECT2,4:CONST.SMPSTATE_EXPECT3,5:CONST.SMPSTATE_EXPECT4,7:CONST.SMPSTATE_EXPECT1};if(6===msg.type)return this.init(),this.trigger("trust",[!1]),void 0;if(this.smpstate!==expectStates[msg.type])return this.abort();switch(this.smpstate){case CONST.SMPSTATE_EXPECT1:HLP.debug.call(this,"smp tlv 2");var ind,question;return 7===msg.type&&(ind=msg.msg.indexOf("\0"),question=msg.msg.substring(0,ind),msg.msg=msg.msg.substring(ind+1)),ms=HLP.readLen(msg.msg.substr(0,4)),6!==ms?this.abort():(msg=HLP.unpackMPIs(6,msg.msg.substring(4)),HLP.checkGroup(msg[0],N)&&HLP.checkGroup(msg[3],N)?HLP.ZKP(1,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N))?HLP.ZKP(2,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N))?(this.g3ao=msg[3],this.makeG2s(),r2=HLP.randomExponent(),r3=HLP.randomExponent(),this.c2=this.computeC(3,r2),this.c3=this.computeC(4,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.computeGs(msg[0],msg[3]),this.smpstate=CONST.SMPSTATE_EXPECT0,this.trigger("question",[question]),void 0):this.abort():this.abort():this.abort());case CONST.SMPSTATE_EXPECT2:if(HLP.debug.call(this,"smp tlv 3"),ms=HLP.readLen(msg.msg.substr(0,4)),11!==ms)return this.abort();if(msg=HLP.unpackMPIs(11,msg.msg.substring(4)),!(HLP.checkGroup(msg[0],N)&&HLP.checkGroup(msg[3],N)&&HLP.checkGroup(msg[6],N)&&HLP.checkGroup(msg[7],N)))return this.abort();if(!HLP.ZKP(3,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N)))return this.abort();if(!HLP.ZKP(4,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N)))return this.abort();if(this.g3ao=msg[3],this.computeGs(msg[0],msg[3]),t1=HLP.multPowMod(this.g3,msg[9],msg[6],msg[8],N),t2=HLP.multPowMod(G,msg[9],this.g2,msg[10],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[7],msg[8],N),N),!HLP.ZKP(5,msg[8],t1,t2))return this.abort();var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(6,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.QoQ=HLP.divMod(this.q,msg[7],N),this.PoP=HLP.divMod(this.p,msg[6],N),this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(7,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),this.smpstate=CONST.SMPSTATE_EXPECT4,send=HLP.packINT(8)+HLP.packMPIs([this.p,this.q,cP,d5,d6,this.r,cR,d7]),send=HLP.packTLV(4,send);break;case CONST.SMPSTATE_EXPECT3:if(HLP.debug.call(this,"smp tlv 4"),ms=HLP.readLen(msg.msg.substr(0,4)),8!==ms)return this.abort();if(msg=HLP.unpackMPIs(8,msg.msg.substring(4)),!HLP.checkGroup(msg[0],N)||!HLP.checkGroup(msg[1],N)||!HLP.checkGroup(msg[5],N))return this.abort();if(t1=HLP.multPowMod(this.g3,msg[3],msg[0],msg[2],N),t2=HLP.multPowMod(G,msg[3],this.g2,msg[4],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[1],msg[2],N),N),!HLP.ZKP(6,msg[2],t1,t2))return this.abort();if(t3=HLP.multPowMod(G,msg[7],this.g3ao,msg[6],N),this.QoQ=HLP.divMod(msg[1],this.q,N),t4=HLP.multPowMod(this.QoQ,msg[7],msg[5],msg[6],N),!HLP.ZKP(7,msg[6],t3,t4))return this.abort();this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(8,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),send=HLP.packINT(3)+HLP.packMPIs([this.r,cR,d7]),send=HLP.packTLV(5,send),rab=this.computeRab(msg[5]),trust=!!BigInt.equals(rab,HLP.divMod(msg[0],this.p,N)),this.trigger("trust",[trust,"answered"]),this.init();break;case CONST.SMPSTATE_EXPECT4:return HLP.debug.call(this,"smp tlv 5"),ms=HLP.readLen(msg.msg.substr(0,4)),3!==ms?this.abort():(msg=HLP.unpackMPIs(3,msg.msg.substring(4)),HLP.checkGroup(msg[0],N)?(t3=HLP.multPowMod(G,msg[2],this.g3ao,msg[1],N),t4=HLP.multPowMod(this.QoQ,msg[2],msg[0],msg[1],N),HLP.ZKP(8,msg[1],t3,t4)?(rab=this.computeRab(msg[0]),trust=!!BigInt.equals(rab,this.PoP),this.trigger("trust",[trust,"asked"]),this.init(),void 0):this.abort()):this.abort())}this.sendMsg(send)},SM.prototype.sendMsg=function(send){this.trigger("send",[this.ssid,"\0"+send])},SM.prototype.rcvSecret=function(secret,question){HLP.debug.call(this,"receive secret");var fn,our=!1;this.smpstate===CONST.SMPSTATE_EXPECT0?fn=this.answer:(fn=this.initiate,our=!0),this.makeSecret(our,secret),fn.call(this,question)},SM.prototype.answer=function(){HLP.debug.call(this,"smp answer");var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(5,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.smpstate=CONST.SMPSTATE_EXPECT3;var send=HLP.packINT(11)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3,this.p,this.q,cP,d5,d6]);this.sendMsg(HLP.packTLV(3,send))},SM.prototype.initiate=function(question){HLP.debug.call(this,"smp initiate"),this.smpstate!==CONST.SMPSTATE_EXPECT1&&this.abort(),this.makeG2s(); -var r2=HLP.randomExponent(),r3=HLP.randomExponent();this.c2=this.computeC(1,r2),this.c3=this.computeC(2,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.smpstate=CONST.SMPSTATE_EXPECT2;var send="",type=2;question&&(send+=question,send+="\0",type=7),send+=HLP.packINT(6)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3]),this.sendMsg(HLP.packTLV(type,send))},SM.prototype.abort=function(){this.init(),this.sendMsg(HLP.packTLV(6,"")),this.trigger("abort")}}.call(this),function(){"use strict";function OTR(options){if(!(this instanceof OTR))return new OTR(options);if(options=options||{},options.priv&&!(options.priv instanceof DSA))throw new Error("Requires long-lived DSA key.");if(this.priv=options.priv?options.priv:new DSA,this.fragment_size=options.fragment_size||0,this.fragment_size<0)throw new Error("Fragment size must be a positive integer.");if(this.send_interval=options.send_interval||0,this.send_interval<0)throw new Error("Send interval must be a positive integer.");this.outgoing=[],this.our_instance_tag=options.instance_tag||OTR.makeInstanceTag(),this.debug=!!options.debug,this.smw=options.smw,this.init();var self=this;["sendMsg","receiveMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)}),EventEmitter.call(this)}var CryptoJS,BigInt,EventEmitter,Worker,SMWPath,CONST,HLP,Parse,AKE,SM,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=OTR,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),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"),AKE=require("./ake.js"),SM=require("./sm.js"),DSA=require("./dsa.js"),OTR.CONST=CONST):(Object.keys(root.OTR).forEach(function(k){OTR[k]=root.OTR[k]}),root.OTR=OTR,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,AKE=OTR.AKE,SM=OTR.SM,DSA=root.DSA);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),MAX_INT=Math.pow(2,53)-1,MAX_UINT=Math.pow(2,31)-1;HLP.extend(OTR,EventEmitter),OTR.prototype.init=function(){this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.authstate=CONST.AUTHSTATE_NONE,this.ALLOW_V2=!0,this.ALLOW_V3=!0,this.REQUIRE_ENCRYPTION=!1,this.SEND_WHITESPACE_TAG=!1,this.WHITESPACE_START_AKE=!1,this.ERROR_START_AKE=!1,Parse.initFragment(this),this.their_y=null,this.their_old_y=null,this.their_keyid=0,this.their_priv_pk=null,this.their_instance_tag="\0\0\0\0",this.our_dh=this.dh(),this.our_old_dh=this.dh(),this.our_keyid=2,this.sessKeys=[new Array(2),new Array(2)],this.storedMgs=[],this.oldMacKeys=[],this.sm=null,this._akeInit(),this.receivedPlaintext=!1},OTR.prototype._akeInit=function(){this.ake=new AKE(this),this.transmittedRS=!1,this.ssid=null},OTR.prototype._SMW=function(otr,reqs){this.otr=otr;var opts={path:SMWPath,seed:BigInt.getSeed};"object"==typeof otr.smw&&Object.keys(otr.smw).forEach(function(k){opts[k]=otr.smw[k]}),this.worker=new Worker(opts.path);var self=this;this.worker.onmessage=function(e){var d=e.data;d&&self.trigger(d.method,d.args)},this.worker.postMessage({type:"seed",seed:opts.seed(),imports:opts.imports}),this.worker.postMessage({type:"init",reqs:reqs})},HLP.extend(OTR.prototype._SMW,EventEmitter),["handleSM","rcvSecret","abort"].forEach(function(m){OTR.prototype._SMW.prototype[m]=function(){this.worker.postMessage({type:"method",method:m,args:Array.prototype.slice.call(arguments,0)})}}),OTR.prototype._smInit=function(){var reqs={ssid:this.ssid,our_fp:this.priv.fingerprint(),their_fp:this.their_priv_pk.fingerprint(),debug:this.debug};this.smw?(this.sm&&this.sm.worker.terminate(),this.sm=new this._SMW(this,reqs)):this.sm=new SM(reqs);var self=this;["trust","abort","question"].forEach(function(e){self.sm.on(e,function(){self.trigger("smp",[e].concat(Array.prototype.slice.call(arguments)))})}),this.sm.on("send",function(ssid,send){self.ssid===ssid&&self._sendMsg(send)})},OTR.prototype.io=function(msg){this.outgoing=this.outgoing.concat(msg);var self=this;!function send(first){if(!first){if(!self.outgoing.length)return;var msg=self.outgoing.shift();self.trigger("io",[msg])}setTimeout(send,first?0:self.send_interval)}(!0)},OTR.prototype.dh=function(){var keys={privateKey:BigInt.randBigInt(320)};return keys.publicKey=BigInt.powMod(G,keys.privateKey,N),keys},OTR.prototype.DHSession=function DHSession(our_dh,their_y){if(!(this instanceof DHSession))return new DHSession(our_dh,their_y);var s=BigInt.powMod(their_y,our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.id=HLP.mask(HLP.h2("\0",secbytes),0,64);var sq=BigInt.greater(our_dh.publicKey,their_y),sendbyte=sq?"":"",rcvbyte=sq?"":"";this.sendenc=HLP.mask(HLP.h1(sendbyte,secbytes),0,128),this.sendmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.sendenc)),this.sendmac=this.sendmac.toString(CryptoJS.enc.Latin1),this.sendmacused=!1,this.rcvenc=HLP.mask(HLP.h1(rcvbyte,secbytes),0,128),this.rcvmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.rcvenc)),this.rcvmac=this.rcvmac.toString(CryptoJS.enc.Latin1),this.rcvmacused=!1,this.extra_symkey=HLP.h2("ÿ",secbytes),this.send_counter=0,this.rcv_counter=0},OTR.prototype.rotateOurKeys=function(){var self=this;this.sessKeys[1].forEach(function(sk){sk&&sk.sendmacused&&self.oldMacKeys.push(sk.sendmac),sk&&sk.rcvmacused&&self.oldMacKeys.push(sk.rcvmac)}),this.our_old_dh=this.our_dh,this.our_dh=this.dh(),this.our_keyid+=1,this.sessKeys[1][0]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[0][1],this.sessKeys[0]=[this.their_y?new this.DHSession(this.our_dh,this.their_y):null,this.their_old_y?new this.DHSession(this.our_dh,this.their_old_y):null]},OTR.prototype.rotateTheirKeys=function(their_y){this.their_keyid+=1;var self=this;this.sessKeys.forEach(function(sk){sk[1]&&sk[1].sendmacused&&self.oldMacKeys.push(sk[1].sendmac),sk[1]&&sk[1].rcvmacused&&self.oldMacKeys.push(sk[1].rcvmac)}),this.their_old_y=this.their_y,this.sessKeys[0][1]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[1][0],this.their_y=their_y,this.sessKeys[0][0]=new this.DHSession(this.our_dh,this.their_y),this.sessKeys[1][0]=new this.DHSession(this.our_old_dh,this.their_y)},OTR.prototype.prepareMsg=function(msg,esk){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||0===this.their_keyid)return this.error("Not ready to encrypt.");var sessKeys=this.sessKeys[1][0];if(sessKeys.send_counter>=MAX_INT)return this.error("Should have rekeyed by now.");sessKeys.send_counter+=1;var ctr=HLP.packCtr(sessKeys.send_counter),send=this.ake.otr_version+"",v3=this.ake.otr_version===CONST.OTR_VERSION_3;if(v3&&(send+=this.our_instance_tag,send+=this.their_instance_tag),send+="\0",send+=HLP.packINT(this.our_keyid-1),send+=HLP.packINT(this.their_keyid),send+=HLP.packMPI(this.our_dh.publicKey),send+=ctr.substring(0,8),Math.ceil(msg.length/8)>=MAX_UINT)return this.error("Message is too long.");var aes=HLP.encryptAes(CryptoJS.enc.Latin1.parse(msg),sessKeys.sendenc,ctr);return send+=HLP.packData(aes),send+=HLP.make1Mac(send,sessKeys.sendmac),send+=HLP.packData(this.oldMacKeys.splice(0).join("")),sessKeys.sendmacused=!0,send=HLP.wrapMsg(send,this.fragment_size,v3,this.our_instance_tag,this.their_instance_tag),send[0]?this.error(send[0]):(esk&&this.trigger("file",["send",sessKeys.extra_symkey,esk]),send[1])},OTR.prototype.handleDataMsg=function(msg){var vt=msg.version+msg.type;this.ake.otr_version===CONST.OTR_VERSION_3&&(vt+=msg.instance_tags);var types=["BYTE","INT","INT","MPI","CTR","DATA","MAC","DATA"];msg=HLP.splitype(types,msg.msg);var ign=""===msg[0];if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||8!==msg.length)return ign||this.error("Received an unreadable encrypted message.",!0),void 0;var our_keyid=this.our_keyid-HLP.readLen(msg[2]),their_keyid=this.their_keyid-HLP.readLen(msg[1]);if(0>our_keyid||our_keyid>1)return ign||this.error("Not of our latest keys.",!0),void 0;if(0>their_keyid||their_keyid>1)return ign||this.error("Not of your latest keys.",!0),void 0;var their_y=their_keyid?this.their_old_y:this.their_y;if(1===their_keyid&&!their_y)return ign||this.error("Do not have that key."),void 0;var sessKeys=this.sessKeys[our_keyid][their_keyid],ctr=HLP.unpackCtr(msg[4]);if(ctr<=sessKeys.rcv_counter)return ign||this.error("Counter in message is not larger."),void 0;sessKeys.rcv_counter=ctr,vt+=msg.slice(0,6).join("");var vmac=HLP.make1Mac(vt,sessKeys.rcvmac);if(!HLP.compare(msg[6],vmac))return ign||this.error("MACs do not match."),void 0;sessKeys.rcvmacused=!0;var out=HLP.decryptAes(msg[5].substring(4),sessKeys.rcvenc,HLP.padCtr(msg[4]));out=out.toString(CryptoJS.enc.Latin1),our_keyid||this.rotateOurKeys(),their_keyid||this.rotateTheirKeys(HLP.readMPI(msg[3]));var ind=out.indexOf("\0");return~ind&&(this.handleTLVs(out.substring(ind+1),sessKeys),out=out.substring(0,ind)),out=CryptoJS.enc.Latin1.parse(out),out.toString(CryptoJS.enc.Utf8)},OTR.prototype.handleTLVs=function(tlvs,sessKeys){for(var type,len,msg;tlvs.length&&(type=HLP.unpackSHORT(tlvs.substr(0,2)),len=HLP.unpackSHORT(tlvs.substr(2,2)),msg=tlvs.substr(4,len),!(msg.length0&&this.doAKE(msg)}msg.msg&&this.trigger("ui",[msg.msg,msg.encrypted])}},OTR.prototype.checkInstanceTags=function(it){var their_it=HLP.readLen(it.substr(0,4)),our_it=HLP.readLen(it.substr(4,4));if(our_it&&our_it!==HLP.readLen(this.our_instance_tag))return!0;if(HLP.readLen(this.their_instance_tag)){if(HLP.readLen(this.their_instance_tag)!==their_it)return!0}else{if(100>their_it)return!0;this.their_instance_tag=HLP.packINT(their_it)}},OTR.prototype.doAKE=function(msg){this.ALLOW_V3&&~msg.ver.indexOf(CONST.OTR_VERSION_3)?this.ake.initiateAKE(CONST.OTR_VERSION_3):this.ALLOW_V2&&~msg.ver.indexOf(CONST.OTR_VERSION_2)?this.ake.initiateAKE(CONST.OTR_VERSION_2):this.error("OTR conversation requested, but no compatible protocol version found.")},OTR.prototype.error=function(err,send){return send?(this.debug||(err="An OTR error has occurred."),err="?OTR Error:"+err,this._sendMsg(err,!0),void 0):(this.trigger("error",[err]),void 0)},OTR.prototype.sendStored=function(){var self=this;this.storedMgs.splice(0).forEach(function(msg){self._sendMsg(msg)})},OTR.prototype.sendFile=function(filename){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED)return this.error("Not ready to encrypt.");if(this.ake.otr_version!==CONST.OTR_VERSION_3)return this.error("Protocol v3 required.");if(!filename)return this.error("Please specify a filename.");var l1name=CryptoJS.enc.Utf8.parse(filename);if(l1name=l1name.toString(CryptoJS.enc.Latin1),l1name.length>=65532)return this.error("filename is too long.");var msg="\0";msg+="\0\b",msg+=HLP.packSHORT(4+l1name.length),msg+="\0\0\0",msg+=l1name,msg=this.prepareMsg(msg,filename),msg&&this._sendMsg(msg,!0)},OTR.prototype.endOtr=function(){this.msgstate===CONST.MSGSTATE_ENCRYPTED&&(this.sendMsg("\0\0\0\0"),this.sm&&(this.smw&&this.sm.worker.terminate(),this.sm=null)),this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.receivedPlaintext=!1,this.trigger("status",[CONST.STATUS_END_OTR])},OTR.makeInstanceTag=function(){var num=BigInt.randBigInt(32);return BigInt.greater(BigInt.str2bigInt("100",16),num)?OTR.makeInstanceTag():HLP.packINT(parseInt(BigInt.bigInt2str(num,10),10))}}.call(this),{OTR:this.OTR,DSA:this.DSA}}); \ No newline at end of file +!function(root,factory){"function"==typeof define&&define.amd?define(["bigint","crypto","eventemitter"],function(BigInt,CryptoJS,EventEmitter){var root={BigInt:BigInt,CryptoJS:CryptoJS,EventEmitter:EventEmitter,OTR:{},DSA:{}};return factory.call(root)}):(root.OTR={},root.DSA={},factory.call(root))}(this,function(){return function(){"use strict";var root=this,CONST={N:"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",G:"2",MSGSTATE_PLAINTEXT:0,MSGSTATE_ENCRYPTED:1,MSGSTATE_FINISHED:2,AUTHSTATE_NONE:0,AUTHSTATE_AWAITING_DHKEY:1,AUTHSTATE_AWAITING_REVEALSIG:2,AUTHSTATE_AWAITING_SIG:3,WHITESPACE_TAG:" ",WHITESPACE_TAG_V2:" ",WHITESPACE_TAG_V3:" ",OTR_TAG:"?OTR",OTR_VERSION_1:"\x00",OTR_VERSION_2:"\x00",OTR_VERSION_3:"\x00",SMPSTATE_EXPECT0:0,SMPSTATE_EXPECT1:1,SMPSTATE_EXPECT2:2,SMPSTATE_EXPECT3:3,SMPSTATE_EXPECT4:4,STATUS_SEND_QUERY:0,STATUS_AKE_INIT:1,STATUS_AKE_SUCCESS:2,STATUS_END_OTR:3};"undefined"!=typeof module&&module.exports?module.exports=CONST:root.OTR.CONST=CONST}.call(this),function(){"use strict";var CryptoJS,BigInt,root=this,HLP={};"undefined"!=typeof module&&module.exports?(module.exports=HLP={},CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js")):(root.OTR&&(root.OTR.HLP=HLP),root.DSA&&(root.DSA.HLP=HLP),CryptoJS=root.CryptoJS,BigInt=root.BigInt);var DTS={BYTE:1,SHORT:2,INT:4,CTR:8,MAC:20,SIG:40},WRAPPER_BEGIN="?OTR",WRAPPER_END=".",TWO=BigInt.str2bigInt("2",10);HLP.debug=function(msg){this.debug&&"function"!=typeof this.debug&&"undefined"!=typeof console&&console.log(msg)},HLP.extend=function(child,parent){function Ctor(){this.constructor=child}for(var key in parent)Object.hasOwnProperty.call(parent,key)&&(child[key]=parent[key]);Ctor.prototype=parent.prototype,child.prototype=new Ctor,child.__super__=parent.prototype},HLP.compare=function(str1,str2){if(str1.length!==str2.length)return!1;for(var i=0,result=0;i0;bytes--)nex=val.length?val.substr(-2,2):"0",val=val.substr(0,val.length-2),res=_toString(parseInt(nex,16))+res;return res},HLP.packINT=function(d){return HLP.packBytes(d,DTS.INT)},HLP.packCtr=function(d){return HLP.padCtr(HLP.packBytes(d,DTS.CTR))},HLP.padCtr=function(ctr){return ctr+"\x00\x00\x00\x00\x00\x00\x00\x00"},HLP.unpackCtr=function(d){return d=HLP.toByteArray(d.substring(0,8)),HLP.unpack(d)},HLP.unpack=function(arr){for(var val=0,i=0,len=arr.length;len>i;i++)val=256*val+arr[i];return val},HLP.packData=function(d){return HLP.packINT(d.length)+d},HLP.bits2bigInt=function(bits){return bits=HLP.toByteArray(bits),BigInt.ba2bigInt(bits)},HLP.packMPI=function(mpi){return HLP.packData(BigInt.bigInt2bits(BigInt.trim(mpi,0)))},HLP.packSHORT=function(short){return HLP.packBytes(short,DTS.SHORT)},HLP.unpackSHORT=function(short){return short=HLP.toByteArray(short),HLP.unpack(short)},HLP.packTLV=function(type,value){return HLP.packSHORT(type)+HLP.packSHORT(value.length)+value},HLP.readLen=function(msg){return msg=HLP.toByteArray(msg.substring(0,4)),HLP.unpack(msg)},HLP.readData=function(data){var n=HLP.unpack(data.splice(0,4));return[n,data]},HLP.readMPI=function(data){return data=HLP.toByteArray(data),data=HLP.readData(data),BigInt.ba2bigInt(data[1])},HLP.packMPIs=function(arr){return arr.reduce(function(prv,cur){return prv+HLP.packMPI(cur)},"")},HLP.unpackMPIs=function(num,mpis){for(var i=0,arr=[];num>i;i++)arr.push("MPI");return HLP.splitype(arr,mpis).map(function(m){return HLP.readMPI(m)})},HLP.wrapMsg=function(msg,fs,v3,our_it,their_it){msg=CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg)),msg=WRAPPER_BEGIN+":"+msg+WRAPPER_END;var its;if(v3&&(its="|",its+=HLP.readLen(our_it).toString(16),its+="|",its+=HLP.readLen(their_it).toString(16)),!fs)return[null,msg];var n=Math.ceil(msg.length/fs);if(n>65535)return["Too many fragments"];if(1==n)return[null,msg];var k,bi,ei,frag,mf,mfs=[];for(k=1;n>=k;k++)bi=(k-1)*fs,ei=k*fs,frag=msg.slice(bi,ei),mf=WRAPPER_BEGIN,v3&&(mf+=its),mf+=","+k+",",mf+=n+",",mf+=frag+",",mfs.push(mf);return[null,mfs]},HLP.splitype=function splitype(arr,msg){var data=[];return arr.forEach(function(a){var str;switch(a){case"PUBKEY":str=splitype(["SHORT","MPI","MPI","MPI","MPI"],msg).join("");break;case"DATA":case"MPI":str=msg.substring(0,HLP.readLen(msg)+4);break;default:str=msg.substring(0,DTS[a])}data.push(str),msg=msg.substring(str.length)}),data};var _bin2num=function(){for(var i=0,_bin2num={};256>i;++i)_bin2num[String.fromCharCode(i)]=i;for(i=128;256>i;++i)_bin2num[String.fromCharCode(63232+i)]=i;return _bin2num}();HLP.toByteArray=function(data){for(var rv=[],ary=data.split(""),i=-1,iz=ary.length,remain=iz%8;remain--;)++i,rv[i]=_bin2num[ary[i]];for(remain=iz>>3;remain--;)rv.push(_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]],_bin2num[ary[++i]]);return rv}}.call(this),function(){"use strict";function timer(){var start=(new Date).getTime();return function(s){if(DEBUG&&"undefined"!=typeof console){var t=(new Date).getTime();console.log(s+": "+(t-start)),start=t}}}function makeRandom(min,max){var c=BigInt.randBigInt(BigInt.bitSize(max));return HLP.between(c,min,max)?c:makeRandom(min,max)}function isProbPrime(k,n){var i,B=3e4,l=BigInt.bitSize(k),primes=BigInt.primes;for(0===primes.length&&(primes=BigInt.findPrimes(B)),rpprb.length!=k.length&&(rpprb=BigInt.dup(k)),i=0;ii;i++){for(BigInt.randBigInt_(rpprb,l,0);!BigInt.greater(k,rpprb);)BigInt.randBigInt_(rpprb,l,0);if(!BigInt.millerRabin(k,rpprb))return 0}return 1}function generatePrimes(bit_length){for(var q,p,rem,counter,t=timer(),repeat=bit_lengths[bit_length].repeat,N=bit_lengths[bit_length].N,LM1=BigInt.twoToThe(bit_length-1),bl4=4*bit_length,brk=!1;;)if(q=BigInt.randBigInt(N,1),q[0]|=1,isProbPrime(q,repeat)){for(t("q"),counter=0;bl4>counter;counter++)if(p=BigInt.randBigInt(bit_length,1),p[0]|=1,rem=BigInt.mod(p,q),rem=BigInt.sub(rem,ONE),p=BigInt.sub(p,rem),!BigInt.greater(LM1,p)&&isProbPrime(p,repeat)){t("p"),primes[bit_length]={p:p,q:q},brk=!0;break}if(brk)break}for(var g,h=BigInt.dup(TWO),pm1=BigInt.sub(p,ONE),e=BigInt.multMod(pm1,BigInt.inverseMod(q,p),p);;){g=BigInt.powMod(h,e,p);{if(!BigInt.equals(g,ONE))return primes[bit_length].g=g,t("g"),void 0;h=BigInt.add(h,ONE)}}throw new Error("Unreachable!")}function DSA(obj,opts){if(!(this instanceof DSA))return new DSA(obj,opts);if(opts=opts||{},obj){var self=this;return["p","q","g","y","x"].forEach(function(prop){self[prop]=obj[prop]}),this.type=obj.type||KEY_TYPE,void 0}var bit_length=parseInt(opts.bit_length?opts.bit_length:1024,10);if(!bit_lengths[bit_length])throw new Error("Unsupported bit length.");primes[bit_length]||generatePrimes(bit_length),this.p=primes[bit_length].p,this.q=primes[bit_length].q,this.g=primes[bit_length].g,this.type=KEY_TYPE,this.x=makeRandom(ZERO,this.q),this.y=BigInt.powMod(this.g,this.x,this.p),opts.nocache&&(primes[bit_length]=null)}function tokenizeStr(str){var start,end;if(start=str.indexOf("("),end=str.lastIndexOf(")"),0>start||0>end)throw new Error("Malformed S-Expression");str=str.substring(start+1,end);var splt=str.search(/\s/),obj={type:str.substring(0,splt),val:[]};if(str=str.substring(splt+1,end),start=str.indexOf("("),0>start)obj.val.push(str);else for(var i,len,ss,es;start>-1;){for(i=start+1,len=str.length,ss=1,es=0;len>i&&ss>es;i++)"("===str[i]&&ss++,")"===str[i]&&es++;obj.val.push(tokenizeStr(str.substring(start,++i))),str=str.substring(++i),start=str.indexOf("(")}return obj}function parseLibotr(obj){if(!obj.type)throw new Error("Parse error.");var o,val;return"privkeys"===obj.type?(o=[],obj.val.forEach(function(i){o.push(parseLibotr(i))}),o):(o={},obj.val.forEach(function(i){val=i.val[0],"string"==typeof val?0===val.indexOf("#")&&(val=val.substring(1,val.lastIndexOf("#")),val=BigInt.str2bigInt(val,16)):val=parseLibotr(i),o[i.type]=val}),o)}var CryptoJS,BigInt,Worker,WWPath,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=DSA,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),WWPath=require("path").join(__dirname,"/dsa-webworker.js"),HLP=require("./helpers.js")):(Object.keys(root.DSA).forEach(function(k){DSA[k]=root.DSA[k]}),root.DSA=DSA,CryptoJS=root.CryptoJS,BigInt=root.BigInt,Worker=root.Worker,WWPath="dsa-webworker.js",HLP=DSA.HLP);var ZERO=BigInt.str2bigInt("0",10),ONE=BigInt.str2bigInt("1",10),TWO=BigInt.str2bigInt("2",10),KEY_TYPE="\x00\x00",DEBUG=!1,rpprb=[],bit_lengths={1024:{N:160,repeat:40},2048:{N:224,repeat:56}},primes={};DSA.prototype={constructor:DSA,packPublic:function(){var str=this.type;return str+=HLP.packMPI(this.p),str+=HLP.packMPI(this.q),str+=HLP.packMPI(this.g),str+=HLP.packMPI(this.y)},packPrivate:function(){var str=this.packPublic()+HLP.packMPI(this.x);return str=CryptoJS.enc.Latin1.parse(str),str.toString(CryptoJS.enc.Base64)},generateNonce:function(m){var priv=BigInt.bigInt2bits(BigInt.trim(this.x,0)),rand=BigInt.bigInt2bits(BigInt.randBigInt(256)),sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(priv)),sha256.update(m),sha256.update(CryptoJS.enc.Latin1.parse(rand));var hash=sha256.finalize();return hash=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1)),BigInt.rightShift_(hash,256-BigInt.bitSize(this.q)),HLP.between(hash,ZERO,this.q)?hash:this.generateNonce(m)},sign:function(m){m=CryptoJS.enc.Latin1.parse(m);for(var k,b=BigInt.str2bigInt(m.toString(CryptoJS.enc.Hex),16),r=ZERO,s=ZERO;BigInt.isZero(s)||BigInt.isZero(r);)k=this.generateNonce(m),r=BigInt.mod(BigInt.powMod(this.g,k,this.p),this.q),BigInt.isZero(r)||(s=BigInt.inverseMod(k,this.q),s=BigInt.mult(s,BigInt.add(b,BigInt.mult(this.x,r))),s=BigInt.mod(s,this.q));return[r,s]},fingerprint:function(){var pk=this.packPublic();return this.type===KEY_TYPE&&(pk=pk.substring(2)),pk=CryptoJS.enc.Latin1.parse(pk),CryptoJS.SHA1(pk).toString(CryptoJS.enc.Hex)}},DSA.parsePublic=function(str,priv){var fields=["SHORT","MPI","MPI","MPI","MPI"];priv&&fields.push("MPI"),str=HLP.splitype(fields,str);var obj={type:str[0],p:HLP.readMPI(str[1]),q:HLP.readMPI(str[2]),g:HLP.readMPI(str[3]),y:HLP.readMPI(str[4])};return priv&&(obj.x=HLP.readMPI(str[5])),new DSA(obj)},DSA.parsePrivate=function(str,libotr){return libotr?parseLibotr(tokenizeStr(str))[0]["private-key"].dsa:(str=CryptoJS.enc.Base64.parse(str),str=str.toString(CryptoJS.enc.Latin1),DSA.parsePublic(str,!0))},DSA.verify=function(key,m,r,s){if(!HLP.between(r,ZERO,key.q)||!HLP.between(s,ZERO,key.q))return!1;var hm=CryptoJS.enc.Latin1.parse(m);hm=BigInt.str2bigInt(hm.toString(CryptoJS.enc.Hex),16);var w=BigInt.inverseMod(s,key.q),u1=BigInt.multMod(hm,w,key.q),u2=BigInt.multMod(r,w,key.q);u1=BigInt.powMod(key.g,u1,key.p),u2=BigInt.powMod(key.y,u2,key.p);var v=BigInt.mod(BigInt.multMod(u1,u2,key.p),key.q);return BigInt.equals(v,r)},DSA.createInWebWorker=function(options,cb){var opts={path:WWPath,seed:BigInt.getSeed};options&&"object"==typeof options&&Object.keys(options).forEach(function(k){opts[k]=options[k]}),"undefined"!=typeof module&&module.exports&&(Worker=require("webworker-threads").Worker);var worker=new Worker(opts.path);worker.onmessage=function(e){var data=e.data;switch(data.type){case"debug":if(!DEBUG||"undefined"==typeof console)return;console.log(data.val);break;case"data":worker.terminate(),cb(DSA.parsePrivate(data.val));break;default:throw new Error("Unrecognized type.")}},worker.postMessage({seed:opts.seed(),imports:opts.imports,debug:DEBUG})}}.call(this),function(){"use strict";var CryptoJS,CONST,HLP,root=this,Parse={};"undefined"!=typeof module&&module.exports?(module.exports=Parse,CryptoJS=require("../vendor/crypto.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.Parse=Parse,CryptoJS=root.CryptoJS,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var tags={};tags[CONST.WHITESPACE_TAG_V2]=CONST.OTR_VERSION_2,tags[CONST.WHITESPACE_TAG_V3]=CONST.OTR_VERSION_3,Parse.parseMsg=function(otr,msg){var ver=[],start=msg.indexOf(CONST.OTR_TAG);if(!~start){if(this.initFragment(otr),ind=msg.indexOf(CONST.WHITESPACE_TAG),~ind){msg=msg.split(""),msg.splice(ind,16);for(var tag,len=msg.length;len>ind;)tag=msg.slice(ind,ind+8).join(""),Object.hasOwnProperty.call(tags,tag)?(msg.splice(ind,8),ver.push(tags[tag])):ind+=8;msg=msg.join("")}return{msg:msg,ver:ver}}var ind=start+CONST.OTR_TAG.length,com=msg[ind];if(","===com||"|"===com)return this.msgFragment(otr,msg.substring(ind+1),"|"===com);if(this.initFragment(otr),~["?","v"].indexOf(com)){"?"===msg[ind]&&(ver.push(CONST.OTR_VERSION_1),ind+=1);var vers={2:CONST.OTR_VERSION_2,3:CONST.OTR_VERSION_3},qs=msg.substring(ind+1),qi=qs.indexOf("?");return qi>=1&&(qs=qs.substring(0,qi).split(""),"v"===msg[ind]&&qs.forEach(function(q){Object.hasOwnProperty.call(vers,q)&&ver.push(vers[q])})),{cls:"query",ver:ver}}if(":"===com){ind+=1;var info=msg.substring(ind,ind+4);if(info.length<4)return{msg:msg};info=CryptoJS.enc.Base64.parse(info).toString(CryptoJS.enc.Latin1);var version=info.substring(0,2),type=info.substring(2);if(!otr["ALLOW_V"+HLP.unpackSHORT(version)])return{msg:msg};ind+=4;var end=msg.substring(ind).indexOf(".");if(!~end)return{msg:msg};msg=CryptoJS.enc.Base64.parse(msg.substring(ind,ind+end)),msg=CryptoJS.enc.Latin1.stringify(msg);var instance_tags;version===CONST.OTR_VERSION_3&&(instance_tags=msg.substring(0,8),msg=msg.substring(8));var cls;return~["","\n","",""].indexOf(type)?cls="ake":""===type&&(cls="data"),{version:version,type:type,msg:msg,cls:cls,instance_tags:instance_tags}}return" Error:"===msg.substring(ind,ind+7)?(otr.ERROR_START_AKE&&otr.sendQueryMsg(),{msg:msg.substring(ind+7),cls:"error"}):{msg:msg}},Parse.initFragment=function(otr){otr.fragment={s:"",j:0,k:0}},Parse.msgFragment=function(otr,msg,v3){if(msg=msg.split(","),v3){var its=msg.shift().split("|"),their_it=HLP.packINT(parseInt(its[0],16)),our_it=HLP.packINT(parseInt(its[1],16));if(otr.checkInstanceTags(their_it+our_it))return}if(!(msg.length<4||isNaN(parseInt(msg[0],10))||isNaN(parseInt(msg[1],10)))){var k=parseInt(msg[0],10),n=parseInt(msg[1],10);return msg=msg[2],k>n||0===n||0===k?(this.initFragment(otr),void 0):(1===k?(this.initFragment(otr),otr.fragment={k:1,n:n,s:msg}):n===otr.fragment.n&&k===otr.fragment.k+1?(otr.fragment.s+=msg,otr.fragment.k+=1):this.initFragment(otr),n===k?(msg=otr.fragment.s,this.initFragment(otr),this.parseMsg(otr,msg)):void 0)}}}.call(this),function(){"use strict";function hMac(gx,gy,pk,kid,m){var pass=CryptoJS.enc.Latin1.parse(m),hmac=CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256,pass);return hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gx))),hmac.update(CryptoJS.enc.Latin1.parse(HLP.packMPI(gy))),hmac.update(CryptoJS.enc.Latin1.parse(pk)),hmac.update(CryptoJS.enc.Latin1.parse(kid)),hmac.finalize().toString(CryptoJS.enc.Latin1)}function AKE(otr){if(!(this instanceof AKE))return new AKE(otr);this.otr=otr,this.our_dh=otr.our_old_dh,this.our_keyid=otr.our_keyid-1,this.their_y=null,this.their_keyid=null,this.their_priv_pk=null,this.ssid=null,this.transmittedRS=!1,this.r=null,this.priv=otr.priv;var self=this;["sendMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)})}var CryptoJS,BigInt,CONST,HLP,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=AKE,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),CONST=require("./const.js"),HLP=require("./helpers.js"),DSA=require("./dsa.js")):(root.OTR.AKE=AKE,CryptoJS=root.CryptoJS,BigInt=root.BigInt,CONST=root.OTR.CONST,HLP=root.OTR.HLP,DSA=root.DSA);var N=BigInt.str2bigInt(CONST.N,16),N_MINUS_2=BigInt.sub(N,BigInt.str2bigInt("2",10));AKE.prototype={constructor:AKE,createKeys:function(g){var s=BigInt.powMod(g,this.our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.ssid=HLP.mask(HLP.h2("\x00",secbytes),0,64);var tmp=HLP.h2("",secbytes);this.c=HLP.mask(tmp,0,128),this.c_prime=HLP.mask(tmp,128,128),this.m1=HLP.h2("",secbytes),this.m2=HLP.h2("",secbytes),this.m1_prime=HLP.h2("",secbytes),this.m2_prime=HLP.h2("",secbytes)},verifySignMac:function(mac,aesctr,m2,c,their_y,our_dh_pk,m1,ctr){var vmac=HLP.makeMac(aesctr,m2);if(!HLP.compare(mac,vmac))return["MACs do not match."];var x=HLP.decryptAes(aesctr.substring(4),c,ctr);x=HLP.splitype(["PUBKEY","INT","SIG"],x.toString(CryptoJS.enc.Latin1));var m=hMac(their_y,our_dh_pk,x[0],x[1],m1),pub=DSA.parsePublic(x[0]),r=HLP.bits2bigInt(x[2].substring(0,20)),s=HLP.bits2bigInt(x[2].substring(20));return DSA.verify(pub,m,r,s)?[null,HLP.readLen(x[1]),pub]:["Cannot verify signature of m."]},makeM:function(their_y,m1,c,m2){var pk=this.priv.packPublic(),kid=HLP.packINT(this.our_keyid),m=hMac(this.our_dh.publicKey,their_y,pk,kid,m1);m=this.priv.sign(m);var msg=pk+kid;msg+=BigInt.bigInt2bits(m[0],20),msg+=BigInt.bigInt2bits(m[1],20),msg=CryptoJS.enc.Latin1.parse(msg);var aesctr=HLP.packData(HLP.encryptAes(msg,c,HLP.packCtr(0))),mac=HLP.makeMac(aesctr,m2);return aesctr+mac},akeSuccess:function(version){return HLP.debug.call(this.otr,"success"),BigInt.equals(this.their_y,this.our_dh.publicKey)?this.otr.error("equal keys - we have a problem.",!0):(this.their_keyid!==this.otr.their_keyid&&this.their_keyid!==this.otr.their_keyid-1&&(this.otr.our_old_dh=this.our_dh,this.otr.their_y=this.their_y,this.otr.their_old_y=null,this.otr.their_keyid=this.their_keyid,this.otr.their_priv_pk=this.their_priv_pk,this.otr.sessKeys[0]=[new this.otr.DHSession(this.otr.our_dh,this.otr.their_y),null],this.otr.sessKeys[1]=[new this.otr.DHSession(this.otr.our_old_dh,this.otr.their_y),null]),this.otr.ssid=this.ssid,this.otr.transmittedRS=this.transmittedRS,this.otr_version=version,this.otr.authstate=CONST.AUTHSTATE_NONE,this.otr.msgstate=CONST.MSGSTATE_ENCRYPTED,this.r=null,this.myhashed=null,this.dhcommit=null,this.encrypted=null,this.hashed=null,this.otr.trigger("status",[CONST.STATUS_AKE_SUCCESS]),this.otr.sendStored(),void 0)},handleAKE:function(msg){var send,vsm,type,version=msg.version;switch(msg.type){case"":if(HLP.debug.call(this.otr,"d-h key message"),msg=HLP.splitype(["DATA","DATA"],msg.msg),this.otr.authstate===CONST.AUTHSTATE_AWAITING_DHKEY){var ourHash=HLP.readMPI(this.myhashed),theirHash=HLP.readMPI(msg[1]);if(BigInt.greater(ourHash,theirHash)){type="",send=this.dhcommit;break}this.our_dh=this.otr.dh(),this.otr.authstate=CONST.AUTHSTATE_NONE,this.r=null,this.myhashed=null}else this.otr.authstate===CONST.AUTHSTATE_AWAITING_SIG&&(this.our_dh=this.otr.dh());this.otr.authstate=CONST.AUTHSTATE_AWAITING_REVEALSIG,this.encrypted=msg[0].substring(4),this.hashed=msg[1].substring(4),type="\n",send=HLP.packMPI(this.our_dh.publicKey);break;case"\n":if(HLP.debug.call(this.otr,"reveal signature message"),msg=HLP.splitype(["MPI"],msg.msg),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_DHKEY){if(this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;if(!BigInt.equals(this.their_y,HLP.readMPI(msg[0])))return}if(this.otr.authstate=CONST.AUTHSTATE_AWAITING_SIG,this.their_y=HLP.readMPI(msg[0]),!HLP.checkGroup(this.their_y,N_MINUS_2))return this.otr.error("Illegal g^y.",!0);this.createKeys(this.their_y),type="",send=HLP.packMPI(this.r),send+=this.makeM(this.their_y,this.m1,this.c,this.m2),this.m1=null,this.m2=null,this.c=null;break;case"":if(HLP.debug.call(this.otr,"signature message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_REVEALSIG)return;msg=HLP.splitype(["DATA","DATA","MAC"],msg.msg),this.r=HLP.readMPI(msg[0]);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key);var gxmpi=HLP.decryptAes(this.encrypted,key,HLP.packCtr(0));gxmpi=gxmpi.toString(CryptoJS.enc.Latin1),this.their_y=HLP.readMPI(gxmpi);var hash=CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi));return HLP.compare(this.hashed,hash.toString(CryptoJS.enc.Latin1))?HLP.checkGroup(this.their_y,N_MINUS_2)?(this.createKeys(this.their_y),vsm=this.verifySignMac(msg[2],msg[1],this.m2,this.c,this.their_y,this.our_dh.publicKey,this.m1,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],send=this.makeM(this.their_y,this.m1_prime,this.c_prime,this.m2_prime),this.m1=null,this.m2=null,this.m1_prime=null,this.m2_prime=null,this.c=null,this.c_prime=null,this.sendMsg(version,"",send),this.akeSuccess(version),void 0)):this.otr.error("Illegal g^x.",!0):this.otr.error("Hashed g^x does not match.",!0);case"":if(HLP.debug.call(this.otr,"data message"),this.otr.authstate!==CONST.AUTHSTATE_AWAITING_SIG)return;return msg=HLP.splitype(["DATA","MAC"],msg.msg),vsm=this.verifySignMac(msg[1],msg[0],this.m2_prime,this.c_prime,this.their_y,this.our_dh.publicKey,this.m1_prime,HLP.packCtr(0)),vsm[0]?this.otr.error(vsm[0],!0):(this.their_keyid=vsm[1],this.their_priv_pk=vsm[2],this.m1_prime=null,this.m2_prime=null,this.c_prime=null,this.transmittedRS=!0,this.akeSuccess(version),void 0);default:return}this.sendMsg(version,type,send)},sendMsg:function(version,type,msg){var send=version+type,v3=version===CONST.OTR_VERSION_3;return v3&&(HLP.debug.call(this.otr,"instance tags"),send+=this.otr.our_instance_tag,send+=this.otr.their_instance_tag),send+=msg,send=HLP.wrapMsg(send,this.otr.fragment_size,v3,this.otr.our_instance_tag,this.otr.their_instance_tag),send[0]?this.otr.error(send[0]):(this.otr._sendMsg(send[1],!0),void 0)},initiateAKE:function(version){HLP.debug.call(this.otr,"d-h commit message"),this.otr.trigger("status",[CONST.STATUS_AKE_INIT]),this.otr.authstate=CONST.AUTHSTATE_AWAITING_DHKEY;var gxmpi=HLP.packMPI(this.our_dh.publicKey);gxmpi=CryptoJS.enc.Latin1.parse(gxmpi),this.r=BigInt.randBigInt(128);var key=CryptoJS.enc.Hex.parse(BigInt.bigInt2str(this.r,16));key=CryptoJS.enc.Latin1.stringify(key),this.myhashed=CryptoJS.SHA256(gxmpi),this.myhashed=HLP.packData(this.myhashed.toString(CryptoJS.enc.Latin1)),this.dhcommit=HLP.packData(HLP.encryptAes(gxmpi,key,HLP.packCtr(0))),this.dhcommit+=this.myhashed,this.sendMsg(version,"",this.dhcommit)}}}.call(this),function(){"use strict";function SM(reqs){return this instanceof SM?(this.version=1,this.our_fp=reqs.our_fp,this.their_fp=reqs.their_fp,this.ssid=reqs.ssid,this.debug=!!reqs.debug,this.init(),void 0):new SM(reqs)}var CryptoJS,BigInt,EventEmitter,CONST,HLP,root=this;"undefined"!=typeof module&&module.exports?(module.exports=SM,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),CONST=require("./const.js"),HLP=require("./helpers.js")):(root.OTR.SM=SM,CryptoJS=root.CryptoJS,BigInt=root.BigInt,EventEmitter=root.EventEmitter,CONST=root.OTR.CONST,HLP=root.OTR.HLP);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),N_MINUS_2=BigInt.sub(N,BigInt.str2bigInt("2",10)),Q=BigInt.sub(N,BigInt.str2bigInt("1",10));BigInt.divInt_(Q,2),HLP.extend(SM,EventEmitter),SM.prototype.init=function(){this.smpstate=CONST.SMPSTATE_EXPECT1,this.secret=null},SM.prototype.makeSecret=function(our,secret){var sha256=CryptoJS.algo.SHA256.create();sha256.update(CryptoJS.enc.Latin1.parse(HLP.packBytes(this.version,1))),sha256.update(CryptoJS.enc.Hex.parse(our?this.our_fp:this.their_fp)),sha256.update(CryptoJS.enc.Hex.parse(our?this.their_fp:this.our_fp)),sha256.update(CryptoJS.enc.Latin1.parse(this.ssid)),sha256.update(CryptoJS.enc.Latin1.parse(secret));var hash=sha256.finalize();this.secret=HLP.bits2bigInt(hash.toString(CryptoJS.enc.Latin1))},SM.prototype.makeG2s=function(){this.a2=HLP.randomExponent(),this.a3=HLP.randomExponent(),this.g2a=BigInt.powMod(G,this.a2,N),this.g3a=BigInt.powMod(G,this.a3,N),HLP.checkGroup(this.g2a,N_MINUS_2)&&HLP.checkGroup(this.g3a,N_MINUS_2)||this.makeG2s()},SM.prototype.computeGs=function(g2a,g3a){this.g2=BigInt.powMod(g2a,this.a2,N),this.g3=BigInt.powMod(g3a,this.a3,N)},SM.prototype.computePQ=function(r){this.p=BigInt.powMod(this.g3,r,N),this.q=HLP.multPowMod(G,r,this.g2,this.secret,N)},SM.prototype.computeR=function(){this.r=BigInt.powMod(this.QoQ,this.a3,N)},SM.prototype.computeRab=function(r){return BigInt.powMod(r,this.a3,N)},SM.prototype.computeC=function(v,r){return HLP.smpHash(v,BigInt.powMod(G,r,N))},SM.prototype.computeD=function(r,a,c){return BigInt.subMod(r,BigInt.multMod(a,c,Q),Q)},SM.prototype.handleSM=function(msg){var send,r2,r3,r7,t1,t2,t3,t4,rab,tmp2,cR,d7,ms,trust,expectStates={2:CONST.SMPSTATE_EXPECT1,3:CONST.SMPSTATE_EXPECT2,4:CONST.SMPSTATE_EXPECT3,5:CONST.SMPSTATE_EXPECT4,7:CONST.SMPSTATE_EXPECT1};if(6===msg.type)return this.init(),this.trigger("trust",[!1]),void 0;if(this.smpstate!==expectStates[msg.type])return this.abort();switch(this.smpstate){case CONST.SMPSTATE_EXPECT1:HLP.debug.call(this,"smp tlv 2");var ind,question;return 7===msg.type&&(ind=msg.msg.indexOf("\x00"),question=msg.msg.substring(0,ind),msg.msg=msg.msg.substring(ind+1)),ms=HLP.readLen(msg.msg.substr(0,4)),6!==ms?this.abort():(msg=HLP.unpackMPIs(6,msg.msg.substring(4)),HLP.checkGroup(msg[0],N_MINUS_2)&&HLP.checkGroup(msg[3],N_MINUS_2)?HLP.ZKP(1,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N))?HLP.ZKP(2,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N))?(this.g3ao=msg[3],this.makeG2s(),r2=HLP.randomExponent(),r3=HLP.randomExponent(),this.c2=this.computeC(3,r2),this.c3=this.computeC(4,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.computeGs(msg[0],msg[3]),this.smpstate=CONST.SMPSTATE_EXPECT0,this.trigger("question",[question]),void 0):this.abort():this.abort():this.abort());case CONST.SMPSTATE_EXPECT2:if(HLP.debug.call(this,"smp tlv 3"),ms=HLP.readLen(msg.msg.substr(0,4)),11!==ms)return this.abort();if(msg=HLP.unpackMPIs(11,msg.msg.substring(4)),!(HLP.checkGroup(msg[0],N_MINUS_2)&&HLP.checkGroup(msg[3],N_MINUS_2)&&HLP.checkGroup(msg[6],N_MINUS_2)&&HLP.checkGroup(msg[7],N_MINUS_2)))return this.abort();if(!HLP.ZKP(3,msg[1],HLP.multPowMod(G,msg[2],msg[0],msg[1],N)))return this.abort();if(!HLP.ZKP(4,msg[4],HLP.multPowMod(G,msg[5],msg[3],msg[4],N)))return this.abort();if(this.g3ao=msg[3],this.computeGs(msg[0],msg[3]),t1=HLP.multPowMod(this.g3,msg[9],msg[6],msg[8],N),t2=HLP.multPowMod(G,msg[9],this.g2,msg[10],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[7],msg[8],N),N),!HLP.ZKP(5,msg[8],t1,t2))return this.abort();var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(6,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.QoQ=BigInt.divMod(this.q,msg[7],N),this.PoP=BigInt.divMod(this.p,msg[6],N),this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(7,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),this.smpstate=CONST.SMPSTATE_EXPECT4,send=HLP.packINT(8)+HLP.packMPIs([this.p,this.q,cP,d5,d6,this.r,cR,d7]),send=HLP.packTLV(4,send);break;case CONST.SMPSTATE_EXPECT3:if(HLP.debug.call(this,"smp tlv 4"),ms=HLP.readLen(msg.msg.substr(0,4)),8!==ms)return this.abort();if(msg=HLP.unpackMPIs(8,msg.msg.substring(4)),!HLP.checkGroup(msg[0],N_MINUS_2)||!HLP.checkGroup(msg[1],N_MINUS_2)||!HLP.checkGroup(msg[5],N_MINUS_2))return this.abort();if(t1=HLP.multPowMod(this.g3,msg[3],msg[0],msg[2],N),t2=HLP.multPowMod(G,msg[3],this.g2,msg[4],N),t2=BigInt.multMod(t2,BigInt.powMod(msg[1],msg[2],N),N),!HLP.ZKP(6,msg[2],t1,t2))return this.abort();if(t3=HLP.multPowMod(G,msg[7],this.g3ao,msg[6],N),this.QoQ=BigInt.divMod(msg[1],this.q,N),t4=HLP.multPowMod(this.QoQ,msg[7],msg[5],msg[6],N),!HLP.ZKP(7,msg[6],t3,t4))return this.abort();this.computeR(),r7=HLP.randomExponent(),tmp2=BigInt.powMod(this.QoQ,r7,N),cR=HLP.smpHash(8,BigInt.powMod(G,r7,N),tmp2),d7=this.computeD(r7,this.a3,cR),send=HLP.packINT(3)+HLP.packMPIs([this.r,cR,d7]),send=HLP.packTLV(5,send),rab=this.computeRab(msg[5]),trust=!!BigInt.equals(rab,BigInt.divMod(msg[0],this.p,N)),this.trigger("trust",[trust,"answered"]),this.init();break;case CONST.SMPSTATE_EXPECT4:return HLP.debug.call(this,"smp tlv 5"),ms=HLP.readLen(msg.msg.substr(0,4)),3!==ms?this.abort():(msg=HLP.unpackMPIs(3,msg.msg.substring(4)),HLP.checkGroup(msg[0],N_MINUS_2)?(t3=HLP.multPowMod(G,msg[2],this.g3ao,msg[1],N),t4=HLP.multPowMod(this.QoQ,msg[2],msg[0],msg[1],N),HLP.ZKP(8,msg[1],t3,t4)?(rab=this.computeRab(msg[0]),trust=!!BigInt.equals(rab,this.PoP),this.trigger("trust",[trust,"asked"]),this.init(),void 0):this.abort()):this.abort())}this.sendMsg(send)},SM.prototype.sendMsg=function(send){this.trigger("send",[this.ssid,"\x00"+send])},SM.prototype.rcvSecret=function(secret,question){HLP.debug.call(this,"receive secret");var fn,our=!1;this.smpstate===CONST.SMPSTATE_EXPECT0?fn=this.answer:(fn=this.initiate,our=!0),this.makeSecret(our,secret),fn.call(this,question)},SM.prototype.answer=function(){HLP.debug.call(this,"smp answer");var r4=HLP.randomExponent();this.computePQ(r4);var r5=HLP.randomExponent(),r6=HLP.randomExponent(),tmp=HLP.multPowMod(G,r5,this.g2,r6,N),cP=HLP.smpHash(5,BigInt.powMod(this.g3,r5,N),tmp),d5=this.computeD(r5,r4,cP),d6=this.computeD(r6,this.secret,cP);this.smpstate=CONST.SMPSTATE_EXPECT3;var send=HLP.packINT(11)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3,this.p,this.q,cP,d5,d6]);this.sendMsg(HLP.packTLV(3,send))},SM.prototype.initiate=function(question){HLP.debug.call(this,"smp initiate"),this.smpstate!==CONST.SMPSTATE_EXPECT1&&this.abort(),this.makeG2s(); +var r2=HLP.randomExponent(),r3=HLP.randomExponent();this.c2=this.computeC(1,r2),this.c3=this.computeC(2,r3),this.d2=this.computeD(r2,this.a2,this.c2),this.d3=this.computeD(r3,this.a3,this.c3),this.smpstate=CONST.SMPSTATE_EXPECT2;var send="",type=2;question&&(send+=question,send+="\x00",type=7),send+=HLP.packINT(6)+HLP.packMPIs([this.g2a,this.c2,this.d2,this.g3a,this.c3,this.d3]),this.sendMsg(HLP.packTLV(type,send))},SM.prototype.abort=function(){this.init(),this.sendMsg(HLP.packTLV(6,"")),this.trigger("abort")}}.call(this),function(){"use strict";function OTR(options){if(!(this instanceof OTR))return new OTR(options);if(options=options||{},options.priv&&!(options.priv instanceof DSA))throw new Error("Requires long-lived DSA key.");if(this.priv=options.priv?options.priv:new DSA,this.fragment_size=options.fragment_size||0,this.fragment_size<0)throw new Error("Fragment size must be a positive integer.");if(this.send_interval=options.send_interval||0,this.send_interval<0)throw new Error("Send interval must be a positive integer.");this.outgoing=[],this.our_instance_tag=options.instance_tag||OTR.makeInstanceTag(),this.debug=!!options.debug,this.smw=options.smw,this.init();var self=this;["sendMsg","receiveMsg"].forEach(function(meth){self[meth]=self[meth].bind(self)}),EventEmitter.call(this)}var CryptoJS,BigInt,EventEmitter,Worker,SMWPath,CONST,HLP,Parse,AKE,SM,DSA,root=this;"undefined"!=typeof module&&module.exports?(module.exports=OTR,CryptoJS=require("../vendor/crypto.js"),BigInt=require("../vendor/bigint.js"),EventEmitter=require("../vendor/eventemitter.js"),SMWPath=require("path").join(__dirname,"/sm-webworker.js"),CONST=require("./const.js"),HLP=require("./helpers.js"),Parse=require("./parse.js"),AKE=require("./ake.js"),SM=require("./sm.js"),DSA=require("./dsa.js"),OTR.CONST=CONST):(Object.keys(root.OTR).forEach(function(k){OTR[k]=root.OTR[k]}),root.OTR=OTR,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,AKE=OTR.AKE,SM=OTR.SM,DSA=root.DSA);var G=BigInt.str2bigInt(CONST.G,10),N=BigInt.str2bigInt(CONST.N,16),MAX_INT=Math.pow(2,53)-1,MAX_UINT=Math.pow(2,31)-1;HLP.extend(OTR,EventEmitter),OTR.prototype.init=function(){this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.authstate=CONST.AUTHSTATE_NONE,this.ALLOW_V2=!0,this.ALLOW_V3=!0,this.REQUIRE_ENCRYPTION=!1,this.SEND_WHITESPACE_TAG=!1,this.WHITESPACE_START_AKE=!1,this.ERROR_START_AKE=!1,Parse.initFragment(this),this.their_y=null,this.their_old_y=null,this.their_keyid=0,this.their_priv_pk=null,this.their_instance_tag="\x00\x00\x00\x00",this.our_dh=this.dh(),this.our_old_dh=this.dh(),this.our_keyid=2,this.sessKeys=[new Array(2),new Array(2)],this.storedMgs=[],this.oldMacKeys=[],this.sm=null,this._akeInit(),this.receivedPlaintext=!1},OTR.prototype._akeInit=function(){this.ake=new AKE(this),this.transmittedRS=!1,this.ssid=null},OTR.prototype._SMW=function(otr,reqs){this.otr=otr;var opts={path:SMWPath,seed:BigInt.getSeed};"object"==typeof otr.smw&&Object.keys(otr.smw).forEach(function(k){opts[k]=otr.smw[k]}),"undefined"!=typeof module&&module.exports&&(Worker=require("webworker-threads").Worker),this.worker=new Worker(opts.path);var self=this;this.worker.onmessage=function(e){var d=e.data;d&&self.trigger(d.method,d.args)},this.worker.postMessage({type:"seed",seed:opts.seed(),imports:opts.imports}),this.worker.postMessage({type:"init",reqs:reqs})},HLP.extend(OTR.prototype._SMW,EventEmitter),["handleSM","rcvSecret","abort"].forEach(function(m){OTR.prototype._SMW.prototype[m]=function(){this.worker.postMessage({type:"method",method:m,args:Array.prototype.slice.call(arguments,0)})}}),OTR.prototype._smInit=function(){var reqs={ssid:this.ssid,our_fp:this.priv.fingerprint(),their_fp:this.their_priv_pk.fingerprint(),debug:this.debug};this.smw?(this.sm&&this.sm.worker.terminate(),this.sm=new this._SMW(this,reqs)):this.sm=new SM(reqs);var self=this;["trust","abort","question"].forEach(function(e){self.sm.on(e,function(){self.trigger("smp",[e].concat(Array.prototype.slice.call(arguments)))})}),this.sm.on("send",function(ssid,send){self.ssid===ssid&&self._sendMsg(send)})},OTR.prototype.io=function(msg){this.outgoing=this.outgoing.concat(msg);var self=this;!function send(first){if(!first){if(!self.outgoing.length)return;var msg=self.outgoing.shift();self.trigger("io",[msg])}setTimeout(send,first?0:self.send_interval)}(!0)},OTR.prototype.dh=function(){var keys={privateKey:BigInt.randBigInt(320)};return keys.publicKey=BigInt.powMod(G,keys.privateKey,N),keys},OTR.prototype.DHSession=function DHSession(our_dh,their_y){if(!(this instanceof DHSession))return new DHSession(our_dh,their_y);var s=BigInt.powMod(their_y,our_dh.privateKey,N),secbytes=HLP.packMPI(s);this.id=HLP.mask(HLP.h2("\x00",secbytes),0,64);var sq=BigInt.greater(our_dh.publicKey,their_y),sendbyte=sq?"":"",rcvbyte=sq?"":"";this.sendenc=HLP.mask(HLP.h1(sendbyte,secbytes),0,128),this.sendmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.sendenc)),this.sendmac=this.sendmac.toString(CryptoJS.enc.Latin1),this.sendmacused=!1,this.rcvenc=HLP.mask(HLP.h1(rcvbyte,secbytes),0,128),this.rcvmac=CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.rcvenc)),this.rcvmac=this.rcvmac.toString(CryptoJS.enc.Latin1),this.rcvmacused=!1,this.extra_symkey=HLP.h2("ÿ",secbytes),this.send_counter=0,this.rcv_counter=0},OTR.prototype.rotateOurKeys=function(){var self=this;this.sessKeys[1].forEach(function(sk){sk&&sk.sendmacused&&self.oldMacKeys.push(sk.sendmac),sk&&sk.rcvmacused&&self.oldMacKeys.push(sk.rcvmac)}),this.our_old_dh=this.our_dh,this.our_dh=this.dh(),this.our_keyid+=1,this.sessKeys[1][0]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[0][1],this.sessKeys[0]=[this.their_y?new this.DHSession(this.our_dh,this.their_y):null,this.their_old_y?new this.DHSession(this.our_dh,this.their_old_y):null]},OTR.prototype.rotateTheirKeys=function(their_y){this.their_keyid+=1;var self=this;this.sessKeys.forEach(function(sk){sk[1]&&sk[1].sendmacused&&self.oldMacKeys.push(sk[1].sendmac),sk[1]&&sk[1].rcvmacused&&self.oldMacKeys.push(sk[1].rcvmac)}),this.their_old_y=this.their_y,this.sessKeys[0][1]=this.sessKeys[0][0],this.sessKeys[1][1]=this.sessKeys[1][0],this.their_y=their_y,this.sessKeys[0][0]=new this.DHSession(this.our_dh,this.their_y),this.sessKeys[1][0]=new this.DHSession(this.our_old_dh,this.their_y)},OTR.prototype.prepareMsg=function(msg,esk){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||0===this.their_keyid)return this.error("Not ready to encrypt.");var sessKeys=this.sessKeys[1][0];if(sessKeys.send_counter>=MAX_INT)return this.error("Should have rekeyed by now.");sessKeys.send_counter+=1;var ctr=HLP.packCtr(sessKeys.send_counter),send=this.ake.otr_version+"",v3=this.ake.otr_version===CONST.OTR_VERSION_3;if(v3&&(send+=this.our_instance_tag,send+=this.their_instance_tag),send+="\x00",send+=HLP.packINT(this.our_keyid-1),send+=HLP.packINT(this.their_keyid),send+=HLP.packMPI(this.our_dh.publicKey),send+=ctr.substring(0,8),Math.ceil(msg.length/8)>=MAX_UINT)return this.error("Message is too long.");var aes=HLP.encryptAes(CryptoJS.enc.Latin1.parse(msg),sessKeys.sendenc,ctr);return send+=HLP.packData(aes),send+=HLP.make1Mac(send,sessKeys.sendmac),send+=HLP.packData(this.oldMacKeys.splice(0).join("")),sessKeys.sendmacused=!0,send=HLP.wrapMsg(send,this.fragment_size,v3,this.our_instance_tag,this.their_instance_tag),send[0]?this.error(send[0]):(esk&&this.trigger("file",["send",sessKeys.extra_symkey,esk]),send[1])},OTR.prototype.handleDataMsg=function(msg){var vt=msg.version+msg.type;this.ake.otr_version===CONST.OTR_VERSION_3&&(vt+=msg.instance_tags);var types=["BYTE","INT","INT","MPI","CTR","DATA","MAC","DATA"];msg=HLP.splitype(types,msg.msg);var ign=""===msg[0];if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED||8!==msg.length)return ign||this.error("Received an unreadable encrypted message.",!0),void 0;var our_keyid=this.our_keyid-HLP.readLen(msg[2]),their_keyid=this.their_keyid-HLP.readLen(msg[1]);if(0>our_keyid||our_keyid>1)return ign||this.error("Not of our latest keys.",!0),void 0;if(0>their_keyid||their_keyid>1)return ign||this.error("Not of your latest keys.",!0),void 0;var their_y=their_keyid?this.their_old_y:this.their_y;if(1===their_keyid&&!their_y)return ign||this.error("Do not have that key."),void 0;var sessKeys=this.sessKeys[our_keyid][their_keyid],ctr=HLP.unpackCtr(msg[4]);if(ctr<=sessKeys.rcv_counter)return ign||this.error("Counter in message is not larger."),void 0;sessKeys.rcv_counter=ctr,vt+=msg.slice(0,6).join("");var vmac=HLP.make1Mac(vt,sessKeys.rcvmac);if(!HLP.compare(msg[6],vmac))return ign||this.error("MACs do not match."),void 0;sessKeys.rcvmacused=!0;var out=HLP.decryptAes(msg[5].substring(4),sessKeys.rcvenc,HLP.padCtr(msg[4]));out=out.toString(CryptoJS.enc.Latin1),our_keyid||this.rotateOurKeys(),their_keyid||this.rotateTheirKeys(HLP.readMPI(msg[3]));var ind=out.indexOf("\x00");return~ind&&(this.handleTLVs(out.substring(ind+1),sessKeys),out=out.substring(0,ind)),out=CryptoJS.enc.Latin1.parse(out),out.toString(CryptoJS.enc.Utf8)},OTR.prototype.handleTLVs=function(tlvs,sessKeys){for(var type,len,msg;tlvs.length&&(type=HLP.unpackSHORT(tlvs.substr(0,2)),len=HLP.unpackSHORT(tlvs.substr(2,2)),msg=tlvs.substr(4,len),!(msg.length0&&this.doAKE(msg)}msg.msg&&this.trigger("ui",[msg.msg,msg.encrypted])}},OTR.prototype.checkInstanceTags=function(it){var their_it=HLP.readLen(it.substr(0,4)),our_it=HLP.readLen(it.substr(4,4));if(our_it&&our_it!==HLP.readLen(this.our_instance_tag))return!0;if(HLP.readLen(this.their_instance_tag)){if(HLP.readLen(this.their_instance_tag)!==their_it)return!0}else{if(100>their_it)return!0;this.their_instance_tag=HLP.packINT(their_it)}},OTR.prototype.doAKE=function(msg){this.ALLOW_V3&&~msg.ver.indexOf(CONST.OTR_VERSION_3)?this.ake.initiateAKE(CONST.OTR_VERSION_3):this.ALLOW_V2&&~msg.ver.indexOf(CONST.OTR_VERSION_2)?this.ake.initiateAKE(CONST.OTR_VERSION_2):this.error("OTR conversation requested, but no compatible protocol version found.")},OTR.prototype.error=function(err,send){return send?(this.debug||(err="An OTR error has occurred."),err="?OTR Error:"+err,this._sendMsg(err,!0),void 0):(this.trigger("error",[err]),void 0)},OTR.prototype.sendStored=function(){var self=this;this.storedMgs.splice(0).forEach(function(msg){self._sendMsg(msg)})},OTR.prototype.sendFile=function(filename){if(this.msgstate!==CONST.MSGSTATE_ENCRYPTED)return this.error("Not ready to encrypt.");if(this.ake.otr_version!==CONST.OTR_VERSION_3)return this.error("Protocol v3 required.");if(!filename)return this.error("Please specify a filename.");var l1name=CryptoJS.enc.Utf8.parse(filename);if(l1name=l1name.toString(CryptoJS.enc.Latin1),l1name.length>=65532)return this.error("filename is too long.");var msg="\x00";msg+="\x00\b",msg+=HLP.packSHORT(4+l1name.length),msg+="\x00\x00\x00",msg+=l1name,msg=this.prepareMsg(msg,filename),msg&&this._sendMsg(msg,!0)},OTR.prototype.endOtr=function(){this.msgstate===CONST.MSGSTATE_ENCRYPTED&&(this.sendMsg("\x00\x00\x00\x00"),this.sm&&(this.smw&&this.sm.worker.terminate(),this.sm=null)),this.msgstate=CONST.MSGSTATE_PLAINTEXT,this.receivedPlaintext=!1,this.trigger("status",[CONST.STATUS_END_OTR])},OTR.makeInstanceTag=function(){var num=BigInt.randBigInt(32);return BigInt.greater(BigInt.str2bigInt("100",16),num)?OTR.makeInstanceTag():HLP.packINT(parseInt(BigInt.bigInt2str(num,10),10))}}.call(this),{OTR:this.OTR,DSA:this.DSA}}); \ No newline at end of file diff --git a/build/sm-webworker.js b/build/sm-webworker.js new file mode 100644 index 0000000..301843d --- /dev/null +++ b/build/sm-webworker.js @@ -0,0 +1,60 @@ +;(function (root) { + "use strict"; + + root.OTR = {} + root.crypto = { + randomBytes: function () { + throw new Error("Haven't seeded yet.") + } + } + + // default imports + var imports = [ + 'vendor/salsa20.js' + , 'vendor/bigint.js' + , 'vendor/crypto.js' + , 'vendor/eventemitter.js' + , 'lib/const.js' + , 'lib/helpers.js' + , 'lib/sm.js' + ] + + function wrapPostMessage(method) { + return function () { + postMessage({ + method: method + , args: Array.prototype.slice.call(arguments, 0) + }) + } + } + + var sm + onmessage = function (e) { + var data = e.data + switch (data.type) { + case 'seed': + if (data.imports) imports = data.imports + importScripts.apply(root, imports) + + // use salsa20 since there's no prng in webworkers + var state = new root.Salsa20( + data.seed.slice(0, 32), + data.seed.slice(32) + ) + root.crypto.randomBytes = function (n) { + return state.getBytes(n) + } + break + case 'init': + sm = new root.OTR.SM(data.reqs) + ;['trust','question', 'send', 'abort'].forEach(function (m) { + sm.on(m, wrapPostMessage(m)); + }) + break + case 'method': + sm[data.method].apply(sm, data.args) + break + } + } + +}(this)) \ No newline at end of file diff --git a/changelog.md b/changelog.md index fc0c830..8d38234 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,15 @@ +0.2.8 / 2013-11-11 +================== + + * performance improvements in bigint + * removed salsa20 as a hard dependency + * webworker in node is truly an optional dep + * msCrypto support + * generate dsa key in a webworker + * internal code cleanup + * documentation improvements + 0.2.7 / 2013-10-12 ================== diff --git a/package.json b/package.json index 3797307..bf3dd3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "otr", - "version": "0.2.7", + "version": "0.2.8", "description": "Off-the-Record Messaging Protocol", "homepage": "https://github.com/arlolra/otr", "main": "index.js",