-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
84 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "otr", | ||
"version": "0.2.12", | ||
"version": "0.2.13", | ||
"main": "build/otr.js", | ||
"ignore": [ | ||
"**/.*", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
/*! | ||
otr.js v0.2.12 - 2014-04-15 | ||
otr.js v0.2.13 - 2014-09-07 | ||
(c) 2014 - Arlo Breault <[email protected]> | ||
Freely distributed under the MPL v2.0 license. | ||
|
@@ -141,14 +141,25 @@ | |
child.__super__ = parent.prototype | ||
} | ||
|
||
// assumes 32-bit | ||
function intCompare(x, y) { | ||
var z = ~(x ^ y) | ||
z &= z >> 16 | ||
z &= z >> 8 | ||
z &= z >> 4 | ||
z &= z >> 2 | ||
z &= z >> 1 | ||
return z & 1 | ||
} | ||
|
||
// constant-time string comparison | ||
HLP.compare = function (str1, str2) { | ||
if (str1.length !== str2.length) | ||
return false | ||
var i = 0, result = 0 | ||
for (; i < str1.length; i++) | ||
result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0) | ||
return result === 0 | ||
return intCompare(result, 0) | ||
} | ||
|
||
HLP.randomExponent = function () { | ||
|
@@ -1160,7 +1171,7 @@ | |
HLP.debug.call(this.otr, 'success') | ||
|
||
if (BigInt.equals(this.their_y, this.our_dh.publicKey)) | ||
return this.otr.error('equal keys - we have a problem.', true) | ||
return this.otr.error('equal keys - we have a problem.') | ||
|
||
this.otr.our_old_dh = this.our_dh | ||
this.otr.their_priv_pk = this.their_priv_pk | ||
|
@@ -1267,7 +1278,7 @@ | |
|
||
// verify gy is legal 2 <= gy <= N-2 | ||
if (!HLP.checkGroup(this.their_y, N_MINUS_2)) | ||
return this.otr.error('Illegal g^y.', true) | ||
return this.otr.error('Illegal g^y.') | ||
|
||
this.createKeys(this.their_y) | ||
|
||
|
@@ -1303,11 +1314,11 @@ | |
var hash = CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi)) | ||
|
||
if (!HLP.compare(this.hashed, hash.toString(CryptoJS.enc.Latin1))) | ||
return this.otr.error('Hashed g^x does not match.', true) | ||
return this.otr.error('Hashed g^x does not match.') | ||
|
||
// verify gx is legal 2 <= g^x <= N-2 | ||
if (!HLP.checkGroup(this.their_y, N_MINUS_2)) | ||
return this.otr.error('Illegal g^x.', true) | ||
return this.otr.error('Illegal g^x.') | ||
|
||
this.createKeys(this.their_y) | ||
|
||
|
@@ -1321,7 +1332,7 @@ | |
, this.m1 | ||
, HLP.packCtr(0) | ||
) | ||
if (vsm[0]) return this.otr.error(vsm[0], true) | ||
if (vsm[0]) return this.otr.error(vsm[0]) | ||
|
||
// store their key | ||
this.their_keyid = vsm[1] | ||
|
@@ -1363,7 +1374,7 @@ | |
, this.m1_prime | ||
, HLP.packCtr(0) | ||
) | ||
if (vsm[0]) return this.otr.error(vsm[0], true) | ||
if (vsm[0]) return this.otr.error(vsm[0]) | ||
|
||
// store their key | ||
this.their_keyid = vsm[1] | ||
|
@@ -1920,6 +1931,11 @@ | |
var MAX_INT = Math.pow(2, 53) - 1 // doubles | ||
var MAX_UINT = Math.pow(2, 31) - 1 // bitwise operators | ||
|
||
// an internal callback | ||
function OTRCB(cb) { | ||
this.cb = cb | ||
} | ||
|
||
// OTR contructor | ||
function OTR(options) { | ||
if (!(this instanceof OTR)) return new OTR(options) | ||
|
@@ -2109,8 +2125,13 @@ | |
;(function send(first) { | ||
if (!first) { | ||
if (!self.outgoing.length) return | ||
var elem = self.outgoing.shift() | ||
var elem = self.outgoing.shift(), cb = null | ||
if (elem.meta instanceof OTRCB) { | ||
cb = elem.meta.cb | ||
elem.meta = null | ||
} | ||
self.trigger('io', [elem.msg, elem.meta]) | ||
if (cb) cb() | ||
} | ||
setTimeout(send, first ? 0 : self.send_interval) | ||
}(true)) | ||
|
@@ -2206,12 +2227,12 @@ | |
|
||
OTR.prototype.prepareMsg = function (msg, esk) { | ||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || this.their_keyid === 0) | ||
return this.error('Not ready to encrypt.') | ||
return this.notify('Not ready to encrypt.') | ||
|
||
var sessKeys = this.sessKeys[1][0] | ||
|
||
if (sessKeys.send_counter >= MAX_INT) | ||
return this.error('Should have rekeyed by now.') | ||
return this.notify('Should have rekeyed by now.') | ||
|
||
sessKeys.send_counter += 1 | ||
|
||
|
@@ -2232,7 +2253,7 @@ | |
send += ctr.substring(0, 8) | ||
|
||
if (Math.ceil(msg.length / 8) >= MAX_UINT) // * 16 / 128 | ||
return this.error('Message is too long.') | ||
return this.notify('Message is too long.') | ||
|
||
var aes = HLP.encryptAes( | ||
CryptoJS.enc.Latin1.parse(msg) | ||
|
@@ -2251,7 +2272,7 @@ | |
, this.our_instance_tag | ||
, this.their_instance_tag | ||
) | ||
if (send[0]) return this.error(send[0]) | ||
if (send[0]) return this.notify(send[0]) | ||
|
||
// emit extra symmetric key | ||
if (esk) this.trigger('file', ['send', sessKeys.extra_symkey, esk]) | ||
|
@@ -2272,20 +2293,20 @@ | |
var ign = (msg[0] === '\x01') | ||
|
||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || msg.length !== 8) { | ||
if (!ign) this.error('Received an unreadable encrypted message.', true) | ||
if (!ign) this.error('Received an unreadable encrypted message.') | ||
return | ||
} | ||
|
||
var our_keyid = this.our_keyid - HLP.readLen(msg[2]) | ||
var their_keyid = this.their_keyid - HLP.readLen(msg[1]) | ||
|
||
if (our_keyid < 0 || our_keyid > 1) { | ||
if (!ign) this.error('Not of our latest keys.', true) | ||
if (!ign) this.error('Not of our latest keys.') | ||
return | ||
} | ||
|
||
if (their_keyid < 0 || their_keyid > 1) { | ||
if (!ign) this.error('Not of your latest keys.', true) | ||
if (!ign) this.error('Not of your latest keys.') | ||
return | ||
} | ||
|
||
|
@@ -2380,10 +2401,10 @@ | |
|
||
OTR.prototype.smpSecret = function (secret, question) { | ||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED) | ||
return this.error('Must be encrypted for SMP.') | ||
return this.notify('Must be encrypted for SMP.') | ||
|
||
if (typeof secret !== 'string' || secret.length < 1) | ||
return this.error('Secret is required.') | ||
return this.notify('Secret is required.') | ||
|
||
if (!this.sm) this._smInit() | ||
|
||
|
@@ -2440,7 +2461,7 @@ | |
break | ||
case CONST.MSGSTATE_FINISHED: | ||
this.storedMgs.push({msg: msg, meta: meta}) | ||
this.error('Message cannot be sent at this time.') | ||
this.notify('Message cannot be sent at this time.', 'warn') | ||
return | ||
case CONST.MSGSTATE_ENCRYPTED: | ||
msg = this.prepareMsg(msg) | ||
|
@@ -2461,18 +2482,26 @@ | |
|
||
switch (msg.cls) { | ||
case 'error': | ||
this.error(msg.msg) | ||
this.notify(msg.msg) | ||
return | ||
case 'ake': | ||
if ( msg.version === CONST.OTR_VERSION_3 && | ||
this.checkInstanceTags(msg.instance_tags) | ||
) return // ignore | ||
) { | ||
this.notify( | ||
'Received a message intended for a different session.', 'warn') | ||
return // ignore | ||
} | ||
this.ake.handleAKE(msg) | ||
return | ||
case 'data': | ||
if ( msg.version === CONST.OTR_VERSION_3 && | ||
this.checkInstanceTags(msg.instance_tags) | ||
) return // ignore | ||
) { | ||
this.notify( | ||
'Received a message intended for a different session.', 'warn') | ||
return // ignore | ||
} | ||
msg.msg = this.handleDataMsg(msg) | ||
msg.encrypted = true | ||
break | ||
|
@@ -2484,7 +2513,7 @@ | |
// check for encrypted | ||
if ( this.REQUIRE_ENCRYPTION || | ||
this.msgstate !== CONST.MSGSTATE_PLAINTEXT | ||
) this.error('Received an unencrypted message.') | ||
) this.notify('Received an unencrypted message.', 'warn') | ||
|
||
// received a plaintext message | ||
// stop sending the whitespace tag | ||
|
@@ -2519,20 +2548,19 @@ | |
} else if (this.ALLOW_V2 && ~msg.ver.indexOf(CONST.OTR_VERSION_2)) { | ||
this.ake.initiateAKE(CONST.OTR_VERSION_2) | ||
} else { | ||
// is this an error? | ||
this.error('OTR conversation requested, ' + | ||
'but no compatible protocol version found.') | ||
this.notify('OTR conversation requested, ' + | ||
'but no compatible protocol version found.', 'warn') | ||
} | ||
} | ||
|
||
OTR.prototype.error = function (err, send) { | ||
if (send) { | ||
if (!this.debug) err = "An OTR error has occurred." | ||
err = '?OTR Error:' + err | ||
this.io(err) | ||
return | ||
} | ||
this.trigger('error', [err]) | ||
OTR.prototype.error = function (err) { | ||
if (!this.debug) err = 'An OTR error has occurred.' | ||
this.io('?OTR Error:' + err) | ||
this.notify(err) | ||
} | ||
|
||
OTR.prototype.notify = function (err, severity) { | ||
this.trigger('error', [err, severity || 'error']) | ||
} | ||
|
||
OTR.prototype.sendStored = function () { | ||
|
@@ -2545,18 +2573,18 @@ | |
|
||
OTR.prototype.sendFile = function (filename) { | ||
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED) | ||
return this.error('Not ready to encrypt.') | ||
return this.notify('Not ready to encrypt.') | ||
|
||
if (this.ake.otr_version !== CONST.OTR_VERSION_3) | ||
return this.error('Protocol v3 required.') | ||
return this.notify('Protocol v3 required.') | ||
|
||
if (!filename) return this.error('Please specify a filename.') | ||
if (!filename) return this.notify('Please specify a filename.') | ||
|
||
// utf8 filenames | ||
var l1name = CryptoJS.enc.Utf8.parse(filename) | ||
l1name = l1name.toString(CryptoJS.enc.Latin1) | ||
|
||
if (l1name.length >= 65532) return this.error('filename is too long.') | ||
if (l1name.length >= 65532) return this.notify('Filename is too long.') | ||
|
||
var msg = '\x00' // null byte | ||
msg += '\x00\x08' // type 8 tlv | ||
|
@@ -2568,9 +2596,11 @@ | |
this.io(msg) | ||
} | ||
|
||
OTR.prototype.endOtr = function () { | ||
OTR.prototype.endOtr = function (cb) { | ||
if (this.msgstate === CONST.MSGSTATE_ENCRYPTED) { | ||
this.sendMsg('\x00\x00\x01\x00\x00') | ||
if (typeof cb === 'function') | ||
cb = new OTRCB(cb) | ||
this.sendMsg('\x00\x00\x01\x00\x00', cb) | ||
if (this.sm) { | ||
if (this.smw) this.sm.worker.terminate() // destroy webworker | ||
this.sm = null | ||
|
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters