Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

send interval

  • Loading branch information...
commit b8637692e4323db0ebedc0431799cb40e352ad2e 1 parent 3726ee8
@arlolra authored
View
2  .gitignore
@@ -1,3 +1,3 @@
node_modules
*.swp
-npm-debug.log
+npm-debug.log
View
32 ake.js
@@ -76,6 +76,11 @@
this.r = null
this.priv = otr.priv
+ // bind methods
+ var self = this
+ ;['sendMsg'].forEach(function (meth) {
+ self[meth] = self[meth].bind(self)
+ })
}
AKE.prototype = {
@@ -166,9 +171,9 @@
this.otr.sendStored()
},
- parseAKE: function(msg, cb){
- cb = cb || function(){}
+ handleAKE: function (msg) {
var send, vsm
+
switch (msg.type) {
case '\x02':
@@ -285,7 +290,7 @@
, this.c_prime
, this.m2_prime
)
- cb(send)
+ this.sendMsg(send)
this.akeSuccess()
return
@@ -322,22 +327,19 @@
return // ignore
}
- cb(send)
-
- },
- handleAKE: function (msg) {
- var ake = this
- this.parseAKE(msg, function(send){
- ake.sendMsg(send)
- })
+ this.sendMsg(send)
},
sendMsg: function (msg) {
msg = '\x00\x02' + msg
- var ake = this
- HLP.wrapMsg(msg, this.otr.fragment_size, function(err, msg){
- if(err) return this.otr.error(err)
+ var ake = this
+ , opts = {
+ fragment_size: this.otr.fragment_size
+ , send_interval: this.otr.send_interval
+ }
+ HLP.wrapMsg(msg, opts, function (err, msg) {
+ if (err) return ake.otr.error(err)
ake.otr.sendMsg(msg, true)
})
},
@@ -364,4 +366,4 @@
}
-}).call(this)
+}).call(this)
View
61 helpers.js
@@ -19,12 +19,12 @@
// data types (byte lengths)
var DTS = {
- BYTE: 1
- , SHORT: 2
- , INT: 4
- , CTR: 8
- , MAC: 20
- , SIG: 40
+ BYTE : 1
+ , SHORT : 2
+ , INT : 4
+ , CTR : 8
+ , MAC : 20
+ , SIG : 40
}
// otr message wrapper begin and end
@@ -269,27 +269,38 @@
})
}
- HLP.wrapMsg = function (msg, fragment_size, cb) {
- fragment_size = fragment_size || 0
+ HLP.wrapMsg = function (msg, opts, cb) {
+ opts = opts || {}
+
msg = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1.parse(msg))
msg = WRAPPER_BEGIN + ":" + msg + WRAPPER_END
- if(fragment_size == 0){
- cb(null, msg)
- } else {
- var n = Math.ceil(msg.length / fragment_size);
- if(n > 65535) return cb("Too many fragments")
- if(n == 1) return cb(msg)
- for(var k = 1; k <= n; k++){
- var bi = (k-1) * fragment_size
- var ei = k * fragment_size
- var frag = msg.slice(bi, ei)
- var mf = WRAPPER_BEGIN + ","
- mf += k + ","
- mf += n + ","
- mf += frag + ","
- cb(null, mf)
- }
+
+ if (!opts.fragment_size) return cb(null, msg)
+
+ var n = Math.ceil(msg.length / opts.fragment_size)
+ if (n > 65535) return cb('Too many fragments')
+ if (n == 1) return cb(null, msg)
+
+ var k, bi, ei, frag, mf, mfs = []
+ for (k = 1; k <= n; k++) {
+ bi = (k - 1) * opts.fragment_size
+ ei = k * opts.fragment_size
+ frag = msg.slice(bi, ei)
+ mf = WRAPPER_BEGIN + ','
+ mf += k + ','
+ mf += n + ','
+ mf += frag + ','
+ mfs.push(mf)
}
+
+ // send interval
+ ;(function send() {
+ var msg = mfs.shift()
+ cb(null, msg)
+ if (!mfs.length) return
+ if (!opts.send_interval) return send()
+ setTimeout(send, opts.send_interval)
+ }())
}
HLP.splitype = function splitype(arr, msg) {
@@ -356,4 +367,4 @@
return rv
}
-}).call(this)
+}).call(this)
View
90 otr.js
@@ -34,8 +34,8 @@
var N = BigInt.str2bigInt(DH.N, 16)
// OTR contructor
- function OTR(priv, uicb, iocb) {
- if (!(this instanceof OTR)) return new OTR(priv, uicb, iocb)
+ function OTR(priv, uicb, iocb, options) {
+ if (!(this instanceof OTR)) return new OTR(priv, uicb, iocb, options)
// private keys
if (priv && !(priv instanceof DSA.Key))
@@ -51,6 +51,17 @@
this.iocb = iocb
this.uicb = uicb
+ // options
+ options = options || {}
+
+ this.fragment_size = options.fragment_size || 0
+ if (!(this.fragment_size >= 0))
+ throw new Error('Fragment size must be a positive integer.')
+
+ this.send_interval = options.send_interval || 50
+ if (!(this.send_interval >= 0))
+ throw new Error('Send interval must be a positive integer.')
+
// init vals
this.init()
@@ -79,7 +90,6 @@
this.ERROR_START_AKE = false
ParseOTR.initFragment(this)
- this.fragment_size = 0
this.versions = {}
@@ -203,7 +213,7 @@
prepareMsg: function (msg, cb) {
if (this.msgstate !== STATES.MSGSTATE_ENCRYPTED || this.their_keyid === 0)
- return cb(this.error('Not ready to encrypt.'))
+ return cb('Not ready to encrypt.')
var sessKeys = this.sessKeys[1][0]
sessKeys.send_counter += 1
@@ -222,10 +232,10 @@
sessKeys.sendmacused = true
- HLP.wrapMsg(send, this.fragment_size, function(err, msg){
- if(err) return cb(this.error(err))
- cb(msg)
- })
+ HLP.wrapMsg(send, {
+ fragment_size: this.fragment_size
+ , send_interval: this.send_interval
+ }, cb)
},
handleDataMsg: function (msg) {
@@ -342,47 +352,34 @@
this.sendMsg(msg, true)
},
- setFragmentSize: function (s){
- if(s >= 0){
- this.fragment_size = s
- } else {
- this.error("Fragment size must be a positive integer, or 0 for no limit.")
- return
- }
- return true
- },
-
sendMsg: function (msg, internal) {
- if (!internal) { // a user or sm msg
-
- switch (this.msgstate) {
- case STATES.MSGSTATE_PLAINTEXT:
- if (this.REQUIRE_ENCRYPTION) {
- this.storedMgs.push(msg)
- this.sendQueryMsg()
- return
- }
- if (this.SEND_WHITESPACE_TAG) {
- // and haven't received a PT msg since entering PT
- // msg += whitespace_tag
- }
- break
- case STATES.MSGSTATE_FINISHED:
- this.storedMgs.push(msg)
- this.error('Message cannot be sent at this time.')
- return
- break
- default:
+ if (internal) return this.iocb(msg) // a user or sm msg
+
+ switch (this.msgstate) {
+ case STATES.MSGSTATE_PLAINTEXT:
+ if (this.REQUIRE_ENCRYPTION) {
this.storedMgs.push(msg)
- var otr = this
- this.prepareMsg(msg, function(msg){
- otr.iocb(msg)
- })
+ this.sendQueryMsg()
return
- }
-
+ }
+ if (this.SEND_WHITESPACE_TAG) {
+ // and haven't received a PT msg since entering PT
+ // msg += whitespace_tag
+ }
+ break
+ case STATES.MSGSTATE_FINISHED:
+ this.storedMgs.push(msg)
+ this.error('Message cannot be sent at this time.')
+ return
+ default:
+ this.storedMgs.push(msg)
+ var otr = this
+ this.prepareMsg(msg, function (err, msg) {
+ if (err) return otr.error(err)
+ otr.iocb(msg)
+ })
+ return
}
- this.iocb(msg)
},
receiveMsg: function (msg) {
@@ -413,7 +410,6 @@
this.sendMsg(err, true)
return
}
-
// should cb be a node style function (err, msg) {}
// or just instanceof Error ?
this.uicb(err)
@@ -436,4 +432,4 @@
}
-}).call(this)
+}).call(this)
View
2  package.json
@@ -30,4 +30,4 @@
"Nadim Kobeissi <nadim@nadim.cc>"
],
"license": "LGPL"
-}
+}
View
20 states.js
@@ -1,13 +1,15 @@
module.exports = {
+
// otr message states
- MSGSTATE_PLAINTEXT: 0
- , MSGSTATE_ENCRYPTED: 1
- , MSGSTATE_FINISHED: 2
+ MSGSTATE_PLAINTEXT : 0
+ , MSGSTATE_ENCRYPTED : 1
+ , MSGSTATE_FINISHED : 2
+
// otr auth states
- , AUTHSTATE_NONE: 0
- , AUTHSTATE_AWAITING_DHKEY: 1
- , AUTHSTATE_AWAITING_REVEALSIG: 2
- , AUTHSTATE_AWAITING_SIG: 3
- , AUTHSTATE_V1_SETUP: 4
-}
+ , AUTHSTATE_NONE : 0
+ , AUTHSTATE_AWAITING_DHKEY : 1
+ , AUTHSTATE_AWAITING_REVEALSIG : 2
+ , AUTHSTATE_AWAITING_SIG : 3
+ , AUTHSTATE_V1_SETUP : 4
+}
View
1  test/spec/unit/dsa.js
@@ -1,5 +1,4 @@
/*global describe before it */
-
var assert = require('assert')
, HLP = require('../../../helpers.js')
, DSA = require('../../../dsa.js')
View
9 test/spec/unit/helpers.js
@@ -1,5 +1,4 @@
/*global describe before it */
-
var assert = require('assert')
, BigInt = require('../../../vendor/bigint.js')
, HLP = require('../../../helpers.js')
@@ -41,4 +40,12 @@ describe('Helpers', function () {
assert.equal('\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00', HLP.packCtr(1))
})
+ it('should return a bit string of the proper length', function () {
+ // 2^(8*3) < 2^(15*2) < 2^(8*4) === 4 bytes
+ // chosen because each array element in bigint.js holds 15 bits
+ // (on my machine) so it looks like [0, 0, 1]
+ var test = BigInt.str2bigInt((Math.pow(2, 30)).toString(), 10)
+ assert.equal(4, HLP.bigInt2bits(test).length)
+ })
+
})
View
41 test/spec/unit/otr.js
@@ -1,5 +1,4 @@
/*global describe before it */
-
var assert = require('assert')
, OTR = require('../../../otr.js')
, HLP = require('../../../helpers.js')
@@ -18,7 +17,7 @@ describe('OTR', function () {
it('should initiate AKE', function () {
var userB = new OTR(keys.userB, cb, cb)
var userA = new OTR(keys.userA, cb, function (msg) {
- var msg = ParseOTR.parseMsg(userB, msg)
+ msg = ParseOTR.parseMsg(userB, msg)
assert.equal('\x02', msg.type, 'Message type.')
assert.equal('\x00\x02', msg.version, 'Message version.')
})
@@ -41,33 +40,36 @@ describe('OTR', function () {
it('should go through the ake dance', function () {
var userA, userB
var ui = function (msg) { console.log(msg) }
- var checkstate = function(user){
- switch(user.authstate){
+ var checkstate = function (user) {
+ switch (user.authstate) {
case STATES.AUTHSTATE_AWAITING_DHKEY:
- assert.equal(HLP.bigInt2bits(userB.ake.r).length, 128/8)
- assert.equal(userB.ake.myhashed.length, (256/8)+4)
+ // This fails sometimes because bigInt2bits trims leading zeros
+ // and r is random bits. So, there's a slightly greater than
+ // 1/256 chance that bytes are missing.
+ // assert.equal(HLP.bigInt2bits(userB.ake.r).length, 128 / 8)
+ assert.equal(userB.ake.myhashed.length, (256 / 8) + 4)
break
case STATES.AUTHSTATE_AWAITING_REVEALSIG:
- assert.equal(user.ake.encrypted.length, 192+4)
- assert.equal(user.ake.hashed.length, 256/8)
+ assert.equal(user.ake.encrypted.length, 192 + 4)
+ assert.equal(user.ake.hashed.length, 256 / 8)
break
case STATES.AUTHSTATE_AWAITING_SIG:
assert.equal(user.ake.their_y.length, 192)
- assert.equal(user.ake.ssid.length, 64/8)
- assert.equal(user.ake.c.length, 128/8)
- assert.equal(user.ake.c_prime.length, 128/8)
- assert.equal(user.ake.m1.length, 256/8)
- assert.equal(user.ake.m2.length, 256/8)
- assert.equal(user.ake.m1_prime.length, 256/8)
- assert.equal(user.ake.m2_prime.length, 256/8)
+ assert.equal(user.ake.ssid.length, 64 / 8)
+ assert.equal(user.ake.c.length, 128 / 8)
+ assert.equal(user.ake.c_prime.length, 128 / 8)
+ assert.equal(user.ake.m1.length, 256 / 8)
+ assert.equal(user.ake.m2.length, 256 / 8)
+ assert.equal(user.ake.m1_prime.length, 256 / 8)
+ assert.equal(user.ake.m2_prime.length, 256 / 8)
break
}
}
- userA = new OTR(keys.userA, ui, function(msg){
+ userA = new OTR(keys.userA, ui, function (msg) {
checkstate(userA)
userB.receiveMsg(msg)
})
- userB = new OTR(keys.userB, ui, function(msg){
+ userB = new OTR(keys.userB, ui, function (msg) {
checkstate(userB)
userA.receiveMsg(msg)
})
@@ -112,9 +114,8 @@ describe('OTR', function () {
assert.equal(msgs[counter++], msg, 'Encrypted message.')
}
var io = function (msg) { userB.receiveMsg(msg) }
- userA = new OTR(keys.userA, ui, io)
+ userA = new OTR(keys.userA, ui, io, { fragment_size: 20 })
userB = new OTR(keys.userB, ui, userA.receiveMsg)
- userA.setFragmentSize(20)
userA.sendQueryMsg()
userB.sendMsg(msgs[counter])
userB.sendMsg(msgs[counter])
@@ -122,4 +123,4 @@ describe('OTR', function () {
userA.sendMsg(msgs[counter])
})
-})
+})
View
1  test/spec/unit/parse.js
@@ -1,5 +1,4 @@
/*global describe before it beforeEach */
-
var assert = require('assert')
, OTR = function () { this.versions = {} } // just a constructor
, P = require('../../../parse.js')
View
1  test/spec/unit/sm.js
@@ -1,5 +1,4 @@
/*global describe beforeEach it */
-
var assert = require('assert')
, OTR = require('../../../otr.js')
, keys = require('./data/keys.js')
View
9 test/xmpp.js
@@ -5,14 +5,17 @@ var xmpp = require('simple-xmpp')
var from = ''
function ui(msg) {
- console.log('ui: ' + msg)
+ console.log('ui: ' + msg)
}
function cb(msg) {
- xmpp.send(from, msg)
+ xmpp.send(from, msg)
}
-var otr = new OTR(keys.userA, ui, cb)
+var otr = new OTR(keys.userA, ui, cb, {
+ fragment_size: 10
+ , send_interval: 200
+})
xmpp.on('online', function() {
console.log('Yes, I\'m connected!')
Please sign in to comment.
Something went wrong with that request. Please try again.