otr
Version:
Off-the-Record Messaging Protocol
788 lines (707 loc) • 25.4 kB
JavaScript
/*global describe it */
var assert = require('assert')
, keys = require('./data/keys.js')
, CONST = require('../../../lib/const.js')
, HLP = require('../../../lib/helpers.js')
, Parse = require('../../../lib/parse.js')
, OTR = require('../../../lib/otr.js')
describe('OTR', function () {
"use strict";
it('should initiate a new OTR object', function () {
new OTR({ priv: keys.userA })
})
it('should generate an instance tag', function () {
var tag = HLP.readLen(OTR.makeInstanceTag())
assert.ok(tag >= 0x00000100)
assert.ok(tag <= 0xffffffff)
})
it('should initiate AKE', function (done) {
var userB = new OTR({ priv: keys.userB })
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
msg = Parse.parseMsg(userB, msg)
assert.equal('\x02', msg.type, 'Message type.')
assert.equal('\x00\x02', msg.version, 'Message version.')
done()
})
// query otr
userA.receiveMsg('?OTR?v2?')
})
it('should query with version two', function (done) {
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
assert.equal('?OTRv2?', msg, msg)
done()
})
userA.ALLOW_V3 = false
userA.sendQueryMsg()
})
it('should query with version three', function (done) {
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
assert.equal('?OTRv3?', msg, msg)
done()
})
userA.ALLOW_V2 = false
userA.sendQueryMsg()
})
it('should query with versions two and three', function (done) {
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
assert.equal('?OTRv23?', msg, msg)
done()
})
userA.sendQueryMsg()
})
it('should not send the whitespace tags', function (done) {
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
assert.ok(!~msg.indexOf(CONST.WHITESPACE_TAG))
assert.ok(!~msg.indexOf(CONST.WHITESPACE_TAG_V2))
done()
})
userA.SEND_WHITESPACE_TAG = false
userA.sendMsg('hi')
})
it('should send the whitespace tags', function (done) {
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) {
assert.ok(~msg.indexOf(CONST.WHITESPACE_TAG))
assert.ok(~msg.indexOf(CONST.WHITESPACE_TAG_V2))
assert.ok(~msg.indexOf(CONST.WHITESPACE_TAG_V3))
done()
})
userA.SEND_WHITESPACE_TAG = true
userA.sendMsg('hi')
})
it('plaintext does not start ake', function (done) {
var userB = new OTR({ priv: keys.userB })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('ui', function (msg, enc) {
assert.equal('hi', msg)
assert.ok(!enc)
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
done()
})
userB.on('io', function (msg) { userA.receiveMsg(msg) })
var userA = new OTR({ priv: keys.userA })
userA.on('error', function (err) { assert.ifError(err) })
userA.on('status', function (state) {
if (state === CONST.STATUS_AKE_INIT) {
assert.fail("Ake init.")
}
})
userA.on('io', userB.receiveMsg)
userB.WHITESPACE_START_AKE = true
userA.sendMsg('hi')
})
it('whitespace start ake', function (done) {
var userB = new OTR({ priv: keys.userB })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('ui', function (msg) { assert.equal('hi', msg) })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_INIT) {
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
} else if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
done()
}
})
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userB.WHITESPACE_START_AKE = true
userA.SEND_WHITESPACE_TAG = true
userA.sendMsg('hi')
})
it('should go through the ake dance', function (done) {
var userA, userB, counter = 0
var err = function (err) { assert.ifError(err) }
var ui = function (msg) { assert.ok(!msg, msg) }
var checkstate = function (user) {
switch (counter) {
case 0:
case 1:
assert.equal(user.authstate, CONST.AUTHSTATE_NONE)
break
case 2:
assert.equal(user.authstate, CONST.AUTHSTATE_AWAITING_DHKEY)
// This fails sometimes because MPIs use a minimum-length encoding.
// So, there's a 1/256 chance that first byte is missing.
// assert.equal(HLP.bigInt2bits(userB.ake.r).length, 128 / 8)
assert.equal(user.ake.myhashed.length, (256 / 8) + 4)
break
case 3:
assert.equal(user.authstate, CONST.AUTHSTATE_AWAITING_REVEALSIG)
// Occasionally fails for the same reason as above (195 == 196)
// assert.equal(user.ake.encrypted.length, 192 + 4)
assert.equal(user.ake.hashed.length, 256 / 8)
break
case 4:
assert.equal(user.authstate, CONST.AUTHSTATE_AWAITING_SIG)
// Same, fails (191 == 192).
// assert.equal(user.ake.their_y.length, 192)
assert.equal(user.ake.ssid.length, 64 / 8)
assert.equal(user.ake.c_prime.length, 128 / 8)
assert.equal(user.ake.m1_prime.length, 256 / 8)
assert.equal(user.ake.m2_prime.length, 256 / 8)
// These are nulled out.
// assert.equal(user.ake.c.length, 128 / 8)
// assert.equal(user.ake.m1.length, 256 / 8)
// assert.equal(user.ake.m2.length, 256 / 8)
break
}
counter++
}
userA = new OTR({ priv: keys.userA })
userA.on('ui', ui)
userA.on('error', err)
userA.on('io', function (msg) {
checkstate(userB)
userB.receiveMsg(msg)
})
userB = new OTR({ priv: keys.userB })
userB.on('ui', ui)
userB.on('error', err)
userB.on('io', function (msg) {
checkstate(userA)
userA.receiveMsg(msg)
})
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
userA.sendQueryMsg() // ask to initiate ake
userA.on('status', function (yay) {
if (yay === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted')
done()
}
})
})
it('v2, should go through the ake dance', function (done) {
var err = function (err) { assert.ifError(err) }
var ui = function (msg) { assert.ok(!msg, msg) }
var userA = new OTR({ priv: keys.userA })
userA.on('ui', ui)
userA.on('error', err)
userA.on('io', function (msg) {
userB.receiveMsg(msg)
})
var userB = new OTR({ priv: keys.userB })
userB.on('ui', ui)
userB.on('error', err)
userB.on('io', function (msg) {
userA.receiveMsg(msg)
})
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
userA.ALLOW_V2 = true
userA.ALLOW_V3 = false
userA.ALLOW_V2 = true
userB.ALLOW_V3 = false
userA.sendQueryMsg()
userA.on('status', function (yay) {
if (yay === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted')
done()
}
})
})
it('should not go through the ake dance', function (done) {
var err = function (err) { assert.ifError(err) }
var ui = function (msg) { assert.ok(!msg, msg) }
var userA = new OTR({ priv: keys.userA })
userA.on('ui', ui)
userA.on('error', err)
userA.on('io', function (msg) {
userB.receiveMsg(msg)
})
var userB = new OTR({ priv: keys.userB })
userB.on('ui', ui)
userB.on('error', function (err) {
assert.equal(err, "OTR conversation requested, but no compatible protocol version found.")
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
done()
})
userB.on('io', function (msg) {
userA.receiveMsg(msg)
})
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT, 'Plaintext')
userA.ALLOW_V2 = false
userA.ALLOW_V3 = true
userB.ALLOW_V2 = true
userB.ALLOW_V3 = false
userA.sendQueryMsg()
})
it('should receive an encrypted message', function (done) {
this.timeout(5000)
var msgs = [
'Hope this works.',
'Second message.', 'Third!', '4', '5', '6', '7',
'8888888888888888888'
]
var counter = 0
var ui = function (msg) {
assert.equal(msgs[counter++], msg, 'Encrypted message.')
if (counter > 7) done()
else this.sendMsg(msgs[counter])
}
var err = function (err) { assert.ifError(err) }
var io = function (msg) { userB.receiveMsg(msg) }
var userA = new OTR({ priv: keys.userA })
userA.on('ui', ui.bind(userA))
userA.on('io', io)
userA.on('error', err)
var userB = new OTR({ priv: keys.userB })
userB.on('ui', ui.bind(userB))
userB.on('error', err)
userB.on('io', userA.receiveMsg)
userA.sendQueryMsg()
userB.on('status', function (yay) {
if (yay === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted')
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Encrypted')
userB.sendMsg(msgs[counter])
}
})
})
it('should send v2 fragments', function (done) {
this.timeout(5000)
var msgs = [
'Hope this works.'
, 'Second message.'
, 'This is a bit of a longer message.'
, 'Some messages can be quite long and must be fragmented over several pieces.'
, 'Lalalala alal allaallal alal al alalal alalaaall lal lal la lal ala al ala l al a al al al alalalalal alalal a lal la aal ala lalala l lala lal lala lal la l alal lalaall la lal la'
]
var counter = 0
var userA, userB
var ui = function (ind) {
return function (msg) {
var u = users[ind]
assert.equal(u.u.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Message state unencrypted. Msg: ' + msg)
assert.equal(u.m[u.c++], msg, 'Encrypted message: ' + msg)
if (++counter === msgs.length) done()
}
}
userA = new OTR({
priv: keys.userA
, fragment_size: 200
, send_interval: 40
})
userA.on('io', function (msg) { userB.receiveMsg(msg) })
userA.on('ui', ui(0))
userA.on('error', function (err) { assert.ifError(err) })
userB = new OTR({
priv: keys.userB
, send_interval: 20
})
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('ui', ui(1))
userB.on('error', function (err) { assert.ifError(err) })
userA.ALLOW_V2 = true
userA.ALLOW_V3 = false
userB.ALLOW_V2 = true
userB.ALLOW_V3 = false
userA.REQUIRE_ENCRYPTION = true
userB.REQUIRE_ENCRYPTION = true
var ind, users = [
{ u: userA, m: [], c: 0 }
, { u: userB, m: [], c: 0 }
]
msgs.forEach(function (m) {
ind = Math.floor(Math.random() * 2) // assign the messages randomly
users[ind ? 0 : 1].m.push(m) // expect the other user to receive it
users[ind].u.sendMsg(m)
})
})
it('should send v3 fragments', function (done) {
this.timeout(5000)
var msgs = [
'Hope this works.'
, 'Second message.'
, 'This is a bit of a longer message.'
, 'Some messages can be quite long and must be fragmented over several pieces.'
, 'Lalalala alal allaallal alal al alalal alalaaall lal lal la lal ala al ala l al a al al al alalalalal alalal a lal la aal ala lalala l lala lal lala lal la l alal lalaall la lal la'
]
var counter = 0
var userA, userB
var ui = function (ind) {
return function (msg) {
var u = users[ind]
assert.equal(u.u.msgstate, CONST.MSGSTATE_ENCRYPTED, 'Message state unencrypted. Msg: ' + msg)
assert.equal(u.m[u.c++], msg, 'Encrypted message: ' + msg)
if (++counter === msgs.length) done()
}
}
userA = new OTR({
fragment_size: 200
, send_interval: 40
, priv: keys.userA
})
userA.on('io', function (msg) { userB.receiveMsg(msg) })
userA.on('ui', ui(0))
userA.on('error', function (err) { assert.ifError(err) })
userB = new OTR({
send_interval: 20
, priv: keys.userB
})
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('ui', ui(1))
userB.on('error', function (err) { assert.ifError(err) })
userA.ALLOW_V2 = false
userA.ALLOW_V3 = true
userB.ALLOW_V2 = false
userB.ALLOW_V3 = true
userA.REQUIRE_ENCRYPTION = true
userB.REQUIRE_ENCRYPTION = true
var ind, users = [
{ u: userA, m: [], c: 0 }
, { u: userB, m: [], c: 0 }
]
msgs.forEach(function (m) {
ind = Math.floor(Math.random() * 2) // assign the messages randomly
users[ind ? 0 : 1].m.push(m) // expect the other user to receive it
users[ind].u.sendMsg(m)
})
})
it('should ignore messages with diff instance tags', function (done) {
var userB = new OTR({ priv: keys.userB })
userB.on('ui', function (msg) { assert.ok(!msg, msg) })
userB.on('error', function (err, severity) {
assert.equal(severity, 'warn')
})
userB.on('io', function (msg) { userA.receiveMsg(msg) })
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userA.sendQueryMsg()
userA.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
userA.their_instance_tag = OTR.makeInstanceTag()
userA.sendMsg('hi')
// not great ... assume 'hi' should be ignored in less that 200ms
setTimeout(function () { done() }, 200)
}
})
})
it('should send utf8 data', function (done) {
var m = 'hello يا هلا يا حبيبي خذني إلى القمر'
var userB = new OTR({ priv: keys.userB })
userB.on('ui', function (msg) {
assert.equal(m, msg, msg)
done()
})
userB.on('error', function (err) { assert.ifError(err) })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userA.sendQueryMsg()
userA.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
userA.sendMsg(m)
}
})
})
it('should send a plaintext message', function (done) {
var m = 'test some german characters äöüß'
var userB = new OTR({ priv: keys.userB })
userB.on('ui', function (msg) {
assert.equal(m, msg, msg)
done()
})
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('error', function (err) { assert.ifError(err) })
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userA.sendMsg(m)
})
it('should send an encrypted message when required', function (done) {
var m = 'test some german characters äöüß'
var userB = new OTR({ priv: keys.userB })
userB.on('ui', function (msg) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(m, msg, msg)
done()
})
userB.on('error', function (err) { assert.ifError(err) })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userA.REQUIRE_ENCRYPTION = true
userA.sendMsg(m)
})
it('disconnect when receiving a type 1 TLV', function (done) {
var userB = new OTR({ priv: keys.userB })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
userA.endOtr()
} else if (state === CONST.STATUS_END_OTR) {
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_FINISHED)
done()
}
})
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
userA.sendQueryMsg()
})
it('callback after disconnect msg sent', function (done) {
var userB = new OTR({ priv: keys.userB })
var sent = false
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
userA.endOtr(function () {
assert.ok(sent)
done()
})
} else if (state === CONST.STATUS_END_OTR) {
assert.equal(userB.msgstate, CONST.MSGSTATE_FINISHED)
sent = true
}
})
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
userA.sendQueryMsg()
})
it('callback even when not encrypted', function (done) {
var userB = new OTR({ priv: keys.userB })
userB.endOtr(done)
})
it('callback only once when fragmented', function (done) {
var userB = new OTR({ priv: keys.userB })
var called = false
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
userA.endOtr(function () {
assert.ifError(called)
called = true
setTimeout(done, 60) // after send interval
})
}
})
var userA = new OTR({
priv: keys.userA
, fragment_size: 40
, send_interval: 40
})
userA.on('io', userB.receiveMsg)
userA.sendQueryMsg()
})
it('should confirm extra symmetric keys', function (done) {
var key, filename = 'testfile!@#$äöüß.zip'
var userB = new OTR({ priv: keys.userB })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
userB.on('error', function (err) { assert.ifError(err) })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
userB.sendFile(filename)
}
})
userB.on('file', function (type, keyB, fn) {
assert.equal(type, 'send')
assert.equal(filename, fn)
key = keyB
})
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
userA.on('file', function (type, keyA, fn) {
assert.equal(type, 'receive')
assert.equal(filename, fn)
assert.equal(key, keyA)
done()
})
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
userA.sendQueryMsg()
})
it('should err when encrypted and rcving a plaintext message', function (done) {
var m = 'here we go now here we go now'
var userB = new OTR({ priv: keys.userB })
userB.on('status', function (state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
assert.equal(userA.msgstate, CONST.MSGSTATE_ENCRYPTED)
assert.equal(userB.msgstate, CONST.MSGSTATE_ENCRYPTED)
// send a plaintext msg w/ internal api
// don't do this
userB.io(m)
}
})
userB.on('error', function (err) { assert.ifError(err) })
userB.on('io', function (msg) { userA.receiveMsg(msg) })
var userA = new OTR({ priv: keys.userA })
userA.on('error', function (err) {
assert.ok(err, "We got an error.")
done()
})
userA.on('io', userB.receiveMsg)
userA.on('ui', function (msg, enc) {
assert.ok(msg)
assert.ifError(enc)
})
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
userA.sendQueryMsg()
})
it('should err when require encrypted and rcving a plaintext', function (done) {
var m = 'here we go now here we go now'
var userB = new OTR({ priv: keys.userB })
userB.REQUIRE_ENCRYPTION = true
userB.on('ui', function (msg, enc) {
assert.ok(msg)
assert.ifError(enc)
})
userB.on('error', function (err) {
assert.ok(err, "We got an error.")
done()
})
var userA = new OTR({ priv: keys.userA })
userA.on('io', userB.receiveMsg)
assert.equal(userA.msgstate, CONST.MSGSTATE_PLAINTEXT)
assert.equal(userB.msgstate, CONST.MSGSTATE_PLAINTEXT)
userA.sendMsg(m)
})
it('should passthrough meta data in plaintext mode', function(done) {
var m1 = 'text message'
var m2 = 'meta data'
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg, meta) {
assert.equal(msg, m1)
assert.equal(meta, m2)
done()
})
userA.sendMsg(m1, m2)
})
it('should passthrough meta data in encrypted mode', function(done) {
var m1 = 'text message'
var m2 = 'meta data'
var userA = new OTR({ priv: keys.userA })
var userB = new OTR({ priv: keys.userB })
userA.on('io', function (msg, meta) {
if (userA.msgstate === CONST.MSGSTATE_ENCRYPTED) {
assert.equal(meta, m2)
done()
}
userB.receiveMsg(msg)
})
userA.on('status', function(state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
userA.sendMsg(m1, m2)
}
})
userB.on('io', userA.receiveMsg)
userB.sendQueryMsg()
})
it('should passthrough meta data for stored messages', function(done) {
var m1 = 'text message'
var m2 = 'meta data'
var userA = new OTR({ priv: keys.userA })
var userB = new OTR({ priv: keys.userB })
userA.msgstate = CONST.MSGSTATE_FINISHED;
userA.on('io', function (msg, meta) {
if (userA.msgstate === CONST.MSGSTATE_ENCRYPTED) {
assert.equal(meta, m2)
done()
}
userB.receiveMsg(msg)
})
userB.on('io', userA.receiveMsg)
userA.sendMsg(m1, m2)
userB.sendQueryMsg()
})
it('should passthrough meta data for fragmented messages', function(done) {
var m1 = 'Lalalala alal allaallal alal al alalal alalaaall lal lal la lal ala al ala l al a al al al alalalalal alalal a lal la aal ala lalala l lala lal lala lal la l alal lalaall la lal la'
var m2 = 'meta data'
var userA = new OTR({
priv: keys.userA
, fragment_size: 200
, send_interval: 40
})
var userB = new OTR({ priv: keys.userB, send_interval: 20 })
userA.on('io', function (msg, meta) {
if (userA.msgstate === CONST.MSGSTATE_ENCRYPTED) {
assert.equal(meta, m2)
if (msg.replace(/^\?OTR[^,]+,(\d),(\d)/, '$1') == msg.replace(/^\?OTR[^,]+,(\d),(\d)/, '$2'))
done()
}
userB.receiveMsg(msg)
})
userA.on('status', function(state) {
if (state === CONST.STATUS_AKE_SUCCESS) {
userA.sendMsg(m1, m2)
}
})
userB.on('io', userA.receiveMsg)
userB.sendQueryMsg()
})
it('should check for DH pubkey equality before skipping key replacement', function (done) {
this.timeout(5000)
// issue #47
var err = function (err) { assert.ifError(err) }
var userA = new OTR({ priv: keys.userA })
userA.on('io', function (msg) { userB.receiveMsg(msg) })
userA.on('error', err)
var bIT = OTR.makeInstanceTag()
var userB = new OTR({ priv: keys.userB, instance_tag: bIT })
userB.on('io', userA.receiveMsg)
userB.on('error', err)
var rcvd = 0
userB.on('ui', function (msg, enc) {
assert.ok(enc)
rcvd += 1
if (rcvd === 2) {
rcvd = 0
// userB crashed; start over
userB = new OTR({ priv: keys.userB, instance_tag: bIT })
userB.on('io', userA.receiveMsg)
userB.on('error', err)
userB.on('ui', function (msg, enc) {
assert.ok(enc)
rcvd += 1
if (rcvd === 2) {
done()
}
})
userB.sendQueryMsg()
}
})
userA.on('status', function (state) {
if (state === OTR.CONST.STATUS_AKE_SUCCESS) {
userA.sendMsg("Amsg1 to B1")
userA.sendMsg("Amsg2 to B1")
}
})
userA.sendQueryMsg()
})
it('should passthrough meta data for received message', function (done) {
var m1 = 'text message'
var m2 = 'meta data'
var userA = new OTR({ priv: keys.userA })
userA.on('ui', function (msg, encrypted, meta) {
assert.equal(msg, m1)
assert.equal(meta, m2)
done()
})
userA.receiveMsg(m1, m2)
})
})