Update libsignal-protocol v1.0.0
// FREEBIE
This commit is contained in:
parent
d89c3e8e86
commit
b8fddfbbdd
3 changed files with 18370 additions and 18570 deletions
|
@ -25133,21 +25133,7 @@ run();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* vim: ts=4:sw=4:expandtab
|
/* vim: ts=4:sw=4:expandtab */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -25173,7 +25159,7 @@ var Internal = Internal || {};
|
||||||
var priv = new Uint8Array(privKey);
|
var priv = new Uint8Array(privKey);
|
||||||
priv[0] &= 248;
|
priv[0] &= 248;
|
||||||
priv[31] &= 127;
|
priv[31] &= 127;
|
||||||
priv[31] |= 64
|
priv[31] |= 64;
|
||||||
|
|
||||||
// Where to store the result
|
// Where to store the result
|
||||||
var publicKey_ptr = Module._malloc(32);
|
var publicKey_ptr = Module._malloc(32);
|
||||||
|
|
|
@ -25257,21 +25257,7 @@ run();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* vim: ts=4:sw=4:expandtab
|
/* vim: ts=4:sw=4:expandtab */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -25297,7 +25283,7 @@ var Internal = Internal || {};
|
||||||
var priv = new Uint8Array(privKey);
|
var priv = new Uint8Array(privKey);
|
||||||
priv[0] &= 248;
|
priv[0] &= 248;
|
||||||
priv[31] &= 127;
|
priv[31] &= 127;
|
||||||
priv[31] |= 64
|
priv[31] |= 64;
|
||||||
|
|
||||||
// Where to store the result
|
// Where to store the result
|
||||||
var publicKey_ptr = Module._malloc(32);
|
var publicKey_ptr = Module._malloc(32);
|
||||||
|
@ -35315,7 +35301,7 @@ Curve25519Worker.prototype = {
|
||||||
return curve25519.verify(pubKey, msg, sig);
|
return curve25519.verify(pubKey, msg, sig);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
Internal.Curve = wrapCurve25519(Internal.curve25519);
|
Internal.Curve = wrapCurve25519(Internal.curve25519);
|
||||||
Internal.Curve.async = wrapCurve25519(Internal.curve25519_async);
|
Internal.Curve.async = wrapCurve25519(Internal.curve25519_async);
|
||||||
|
@ -35346,21 +35332,8 @@ Curve25519Worker.prototype = {
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -35487,63 +35460,21 @@ var Internal = Internal || {};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/*
|
||||||
*
|
* vim: ts=4:sw=4
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var util = (function() {
|
var util = (function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var StaticByteBufferProto = new dcodeIO.ByteBuffer().__proto__;
|
|
||||||
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
||||||
var StaticUint8ArrayProto = new Uint8Array().__proto__;
|
|
||||||
|
|
||||||
function stringObject(thing) {
|
|
||||||
if (typeof thing === 'string') {
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
if (thing === Object(thing)) {
|
|
||||||
if (thing.__proto__ == StaticUint8ArrayProto) {
|
|
||||||
return String.fromCharCode.apply(null, thing);
|
|
||||||
}
|
|
||||||
if (thing.__proto__ == StaticArrayBufferProto) {
|
|
||||||
return stringObject(new Uint8Array(thing));
|
|
||||||
}
|
|
||||||
if (thing.__proto__ == StaticByteBufferProto) {
|
|
||||||
return thing.toString('binary');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('unsure how to stringify object of type ' + typeof thing);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toString: function(thing) {
|
toString: function(thing) {
|
||||||
if (typeof thing == 'string') {
|
if (typeof thing == 'string') {
|
||||||
return thing;
|
return thing;
|
||||||
} else if (util.isStringable(thing)) {
|
|
||||||
return util.stringObject(thing);
|
|
||||||
} else {
|
|
||||||
throw new Error("Unsure how to convert object to string from type " + typeof thing);
|
|
||||||
}
|
}
|
||||||
},
|
return new dcodeIO.ByteBuffer.wrap(thing).toString('binary');
|
||||||
stringObject: stringObject,
|
|
||||||
isStringable: function (thing) {
|
|
||||||
return (thing === Object(thing) &&
|
|
||||||
(thing.__proto__ == StaticArrayBufferProto ||
|
|
||||||
thing.__proto__ == StaticUint8ArrayProto ||
|
|
||||||
thing.__proto__ == StaticByteBufferProto));
|
|
||||||
},
|
},
|
||||||
toArrayBuffer: function(thing) {
|
toArrayBuffer: function(thing) {
|
||||||
if (thing === undefined) {
|
if (thing === undefined) {
|
||||||
|
@ -35553,42 +35484,23 @@ var util = (function() {
|
||||||
if (thing.__proto__ == StaticArrayBufferProto) {
|
if (thing.__proto__ == StaticArrayBufferProto) {
|
||||||
return thing;
|
return thing;
|
||||||
}
|
}
|
||||||
//TODO: Several more cases here...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thing instanceof Array) {
|
|
||||||
// Assuming Uint16Array from curve25519
|
|
||||||
//TODO: Move to convertToArrayBuffer
|
|
||||||
var res = new ArrayBuffer(thing.length * 2);
|
|
||||||
var uint = new Uint16Array(res);
|
|
||||||
for (var i = 0; i < thing.length; i++) {
|
|
||||||
uint[i] = thing[i];
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var str;
|
var str;
|
||||||
if (util.isStringable(thing)) {
|
if (typeof thing == "string") {
|
||||||
str = util.stringObject(thing);
|
|
||||||
} else if (typeof thing == "string") {
|
|
||||||
str = thing;
|
str = thing;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Tried to convert a non-stringable thing of type " + typeof thing + " to an array buffer");
|
throw new Error("Tried to convert a non-string of type " + typeof thing + " to an array buffer");
|
||||||
}
|
}
|
||||||
var res = new ArrayBuffer(str.length);
|
return new dcodeIO.ByteBuffer.wrap(thing, 'binary').toArrayBuffer();
|
||||||
var uint = new Uint8Array(res);
|
|
||||||
for (var i = 0; i < str.length; i++) {
|
|
||||||
uint[i] = str.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
},
|
||||||
isEqual: function(a, b) {
|
isEqual: function(a, b) {
|
||||||
// TODO: Special-case arraybuffers, etc
|
// TODO: Special-case arraybuffers, etc
|
||||||
if (a === undefined || b === undefined) {
|
if (a === undefined || b === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a = stringObject(a);
|
a = util.toString(a);
|
||||||
b = stringObject(b);
|
b = util.toString(b);
|
||||||
var maxLength = Math.max(a.length, b.length);
|
var maxLength = Math.max(a.length, b.length);
|
||||||
if (maxLength < 5) {
|
if (maxLength < 5) {
|
||||||
throw new Error("a/b compare too short");
|
throw new Error("a/b compare too short");
|
||||||
|
@ -35683,21 +35595,7 @@ Internal.protoText = function() {
|
||||||
|
|
||||||
return protoText;
|
return protoText;
|
||||||
}();
|
}();
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
Internal.protobuf = function() {
|
Internal.protobuf = function() {
|
||||||
|
@ -35705,7 +35603,7 @@ Internal.protobuf = function() {
|
||||||
|
|
||||||
function loadProtoBufs(filename) {
|
function loadProtoBufs(filename) {
|
||||||
return dcodeIO.ProtoBuf.loadProto(Internal.protoText['protos/' + filename]).build('textsecure');
|
return dcodeIO.ProtoBuf.loadProto(Internal.protoText['protos/' + filename]).build('textsecure');
|
||||||
};
|
}
|
||||||
|
|
||||||
var protocolMessages = loadProtoBufs('WhisperTextProtocol.proto');
|
var protocolMessages = loadProtoBufs('WhisperTextProtocol.proto');
|
||||||
|
|
||||||
|
@ -35715,44 +35613,50 @@ Internal.protobuf = function() {
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
|
Internal.BaseKeyType = {
|
||||||
|
OURS: 1,
|
||||||
|
THEIRS: 2
|
||||||
|
};
|
||||||
|
Internal.ChainType = {
|
||||||
|
SENDING: 1,
|
||||||
|
RECEIVING: 2
|
||||||
|
};
|
||||||
|
|
||||||
Internal.SessionRecord = function() {
|
Internal.SessionRecord = function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
var MESSAGE_LOST_THRESHOLD_MS = 1000*60*60*24*7;
|
var MESSAGE_LOST_THRESHOLD_MS = 1000*60*60*24*7;
|
||||||
|
|
||||||
|
var StaticByteBufferProto = new dcodeIO.ByteBuffer().__proto__;
|
||||||
|
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
||||||
|
var StaticUint8ArrayProto = new Uint8Array().__proto__;
|
||||||
|
|
||||||
|
function isStringable(thing) {
|
||||||
|
return (thing === Object(thing) &&
|
||||||
|
(thing.__proto__ == StaticArrayBufferProto ||
|
||||||
|
thing.__proto__ == StaticUint8ArrayProto ||
|
||||||
|
thing.__proto__ == StaticByteBufferProto));
|
||||||
|
}
|
||||||
function ensureStringed(thing) {
|
function ensureStringed(thing) {
|
||||||
if (typeof thing == "string" || typeof thing == "number" || typeof thing == "boolean") {
|
if (typeof thing == "string" || typeof thing == "number" || typeof thing == "boolean") {
|
||||||
return thing;
|
return thing;
|
||||||
} else if (util.isStringable(thing)) {
|
} else if (isStringable(thing)) {
|
||||||
return util.stringObject(thing);
|
return util.toString(thing);
|
||||||
} else if (thing instanceof Array) {
|
} else if (thing instanceof Array) {
|
||||||
var res = [];
|
var array = [];
|
||||||
for (var i = 0; i < thing.length; i++) {
|
for (var i = 0; i < thing.length; i++) {
|
||||||
res[i] = ensureStringed(thing[i]);
|
array[i] = ensureStringed(thing[i]);
|
||||||
}
|
}
|
||||||
return res;
|
return array;
|
||||||
} else if (thing === Object(thing)) {
|
} else if (thing === Object(thing)) {
|
||||||
var res = {};
|
var obj = {};
|
||||||
for (var key in thing) {
|
for (var key in thing) {
|
||||||
res[key] = ensureStringed(thing[key]);
|
obj[key] = ensureStringed(thing[key]);
|
||||||
}
|
}
|
||||||
return res;
|
return obj;
|
||||||
} else if (thing === null) {
|
} else if (thing === null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -35804,19 +35708,12 @@ Internal.SessionRecord = function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
getSessionByBaseKey: function(baseKey) {
|
getSessionByBaseKey: function(baseKey) {
|
||||||
return this._sessions[util.toString(baseKey)];
|
var session = this._sessions[util.toString(baseKey)];
|
||||||
},
|
if (session && session.indexInfo.baseKeyType === Internal.BaseKeyType.OURS) {
|
||||||
getSessionOrIdentityKeyByBaseKey: function(baseKey) {
|
console.log("Tried to lookup a session using our basekey");
|
||||||
var preferredSession = this.getSessionByBaseKey(baseKey);
|
return undefined;
|
||||||
if (preferredSession !== undefined) {
|
|
||||||
return preferredSession;
|
|
||||||
}
|
}
|
||||||
|
return session;
|
||||||
if (this.identityKey !== undefined) {
|
|
||||||
return { indexInfo: { remoteIdentityKey: this.identityKey } };
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Datastore inconsistency: device was stored without identity key");
|
|
||||||
},
|
},
|
||||||
getSessionByRemoteEphemeralKey: function(remoteEphemeralKey) {
|
getSessionByRemoteEphemeralKey: function(remoteEphemeralKey) {
|
||||||
this.detectDuplicateOpenSessions();
|
this.detectDuplicateOpenSessions();
|
||||||
|
@ -35824,7 +35721,7 @@ Internal.SessionRecord = function() {
|
||||||
|
|
||||||
var searchKey = util.toString(remoteEphemeralKey);
|
var searchKey = util.toString(remoteEphemeralKey);
|
||||||
|
|
||||||
var openSession = undefined;
|
var openSession;
|
||||||
for (var key in sessions) {
|
for (var key in sessions) {
|
||||||
if (sessions[key].indexInfo.closed == -1) {
|
if (sessions[key].indexInfo.closed == -1) {
|
||||||
openSession = sessions[key];
|
openSession = sessions[key];
|
||||||
|
@ -35855,7 +35752,7 @@ Internal.SessionRecord = function() {
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
detectDuplicateOpenSessions: function() {
|
detectDuplicateOpenSessions: function() {
|
||||||
var openSession = undefined;
|
var openSession;
|
||||||
var sessions = this._sessions;
|
var sessions = this._sessions;
|
||||||
for (var key in sessions) {
|
for (var key in sessions) {
|
||||||
if (sessions[key].indexInfo.closed == -1) {
|
if (sessions[key].indexInfo.closed == -1) {
|
||||||
|
@ -35925,8 +35822,8 @@ Internal.SessionRecord = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete current root key and our ephemeral key pair to disallow ratchet stepping
|
// Delete current root key and our ephemeral key pair to disallow ratchet stepping
|
||||||
delete session.currentRatchet['rootKey'];
|
delete session.currentRatchet.rootKey;
|
||||||
delete session.currentRatchet['ephemeralKeyPair'];
|
delete session.currentRatchet.ephemeralKeyPair;
|
||||||
session.indexInfo.closed = Date.now();
|
session.indexInfo.closed = Date.now();
|
||||||
this.removeOldChains(session);
|
this.removeOldChains(session);
|
||||||
},
|
},
|
||||||
|
@ -36185,6 +36082,7 @@ SessionBuilder.prototype = {
|
||||||
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
||||||
if (isInitiator) {
|
if (isInitiator) {
|
||||||
session.indexInfo.baseKey = ourEphemeralKey.pubKey;
|
session.indexInfo.baseKey = ourEphemeralKey.pubKey;
|
||||||
|
session.indexInfo.baseKeyType = Internal.BaseKeyType.OURS;
|
||||||
return Internal.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
return Internal.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
||||||
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
||||||
return this.calculateSendingRatchet(session, theirSignedPubKey).then(function() {
|
return this.calculateSendingRatchet(session, theirSignedPubKey).then(function() {
|
||||||
|
@ -36193,6 +36091,7 @@ SessionBuilder.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
} else {
|
} else {
|
||||||
session.indexInfo.baseKey = theirEphemeralPubKey;
|
session.indexInfo.baseKey = theirEphemeralPubKey;
|
||||||
|
session.indexInfo.baseKeyType = Internal.BaseKeyType.THEIRS;
|
||||||
session.currentRatchet.ephemeralKeyPair = ourSignedKey;
|
session.currentRatchet.ephemeralKeyPair = ourSignedKey;
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
@ -36211,7 +36110,8 @@ SessionBuilder.prototype = {
|
||||||
}).then(function(masterKey) {
|
}).then(function(masterKey) {
|
||||||
session[util.toString(ratchet.ephemeralKeyPair.pubKey)] = {
|
session[util.toString(ratchet.ephemeralKeyPair.pubKey)] = {
|
||||||
messageKeys : {},
|
messageKeys : {},
|
||||||
chainKey : { counter : -1, key : masterKey[1] }
|
chainKey : { counter : -1, key : masterKey[1] },
|
||||||
|
chainType : Internal.ChainType.SENDING
|
||||||
};
|
};
|
||||||
ratchet.rootKey = masterKey[0];
|
ratchet.rootKey = masterKey[0];
|
||||||
});
|
});
|
||||||
|
@ -36276,6 +36176,9 @@ SessionCipher.prototype = {
|
||||||
session.currentRatchet.ephemeralKeyPair.pubKey
|
session.currentRatchet.ephemeralKeyPair.pubKey
|
||||||
);
|
);
|
||||||
chain = session[util.toString(msg.ephemeralKey)];
|
chain = session[util.toString(msg.ephemeralKey)];
|
||||||
|
if (chain.chainType === Internal.ChainType.RECEIVING) {
|
||||||
|
throw new Error("Tried to encrypt on a receiving chain");
|
||||||
|
}
|
||||||
|
|
||||||
return this.fillMessageKeys(chain, chain.chainKey.counter + 1);
|
return this.fillMessageKeys(chain, chain.chainKey.counter + 1);
|
||||||
}.bind(this)).then(function() {
|
}.bind(this)).then(function() {
|
||||||
|
@ -36334,7 +36237,7 @@ SessionCipher.prototype = {
|
||||||
var messageLengthWithTerminator = messageLength + 1;
|
var messageLengthWithTerminator = messageLength + 1;
|
||||||
var messagePartCount = Math.floor(messageLengthWithTerminator / 160);
|
var messagePartCount = Math.floor(messageLengthWithTerminator / 160);
|
||||||
|
|
||||||
if (messageLengthWithTerminator % 160 != 0) {
|
if (messageLengthWithTerminator % 160 !== 0) {
|
||||||
messagePartCount++;
|
messagePartCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36422,6 +36325,9 @@ SessionCipher.prototype = {
|
||||||
|
|
||||||
return this.maybeStepRatchet(session, remoteEphemeralKey, message.previousCounter).then(function() {
|
return this.maybeStepRatchet(session, remoteEphemeralKey, message.previousCounter).then(function() {
|
||||||
var chain = session[util.toString(message.ephemeralKey)];
|
var chain = session[util.toString(message.ephemeralKey)];
|
||||||
|
if (chain.chainType === Internal.ChainType.SENDING) {
|
||||||
|
throw new Error("Tried to decrypt on a sending chain");
|
||||||
|
}
|
||||||
|
|
||||||
return this.fillMessageKeys(chain, message.counter).then(function() {
|
return this.fillMessageKeys(chain, message.counter).then(function() {
|
||||||
var messageKey = chain.messageKeys[message.counter];
|
var messageKey = chain.messageKeys[message.counter];
|
||||||
|
@ -36455,12 +36361,12 @@ SessionCipher.prototype = {
|
||||||
plaintext.set(paddedPlaintext.subarray(0, i));
|
plaintext.set(paddedPlaintext.subarray(0, i));
|
||||||
plaintext = plaintext.buffer;
|
plaintext = plaintext.buffer;
|
||||||
break;
|
break;
|
||||||
} else if (paddedPlaintext[i] != 0x00) {
|
} else if (paddedPlaintext[i] !== 0x00) {
|
||||||
throw new Error('Invalid padding');
|
throw new Error('Invalid padding');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete session['pendingPreKey'];
|
delete session.pendingPreKey;
|
||||||
return plaintext;
|
return plaintext;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -36541,7 +36447,8 @@ SessionCipher.prototype = {
|
||||||
}
|
}
|
||||||
session[util.toString(ephemeralPublicKey)] = {
|
session[util.toString(ephemeralPublicKey)] = {
|
||||||
messageKeys: {},
|
messageKeys: {},
|
||||||
chainKey: { counter: -1, key: masterKey[1] }
|
chainKey: { counter: -1, key: masterKey[1] },
|
||||||
|
chainType: sending ? Internal.ChainType.SENDING : Internal.ChainType.RECEIVING
|
||||||
};
|
};
|
||||||
ratchet.rootKey = masterKey[0];
|
ratchet.rootKey = masterKey[0];
|
||||||
});
|
});
|
||||||
|
|
|
@ -25133,21 +25133,7 @@ run();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* vim: ts=4:sw=4:expandtab
|
/* vim: ts=4:sw=4:expandtab */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -25173,7 +25159,7 @@ var Internal = Internal || {};
|
||||||
var priv = new Uint8Array(privKey);
|
var priv = new Uint8Array(privKey);
|
||||||
priv[0] &= 248;
|
priv[0] &= 248;
|
||||||
priv[31] &= 127;
|
priv[31] &= 127;
|
||||||
priv[31] |= 64
|
priv[31] |= 64;
|
||||||
|
|
||||||
// Where to store the result
|
// Where to store the result
|
||||||
var publicKey_ptr = Module._malloc(32);
|
var publicKey_ptr = Module._malloc(32);
|
||||||
|
@ -35191,7 +35177,7 @@ Curve25519Worker.prototype = {
|
||||||
return curve25519.verify(pubKey, msg, sig);
|
return curve25519.verify(pubKey, msg, sig);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
Internal.Curve = wrapCurve25519(Internal.curve25519);
|
Internal.Curve = wrapCurve25519(Internal.curve25519);
|
||||||
Internal.Curve.async = wrapCurve25519(Internal.curve25519_async);
|
Internal.Curve.async = wrapCurve25519(Internal.curve25519_async);
|
||||||
|
@ -35222,21 +35208,8 @@ Curve25519Worker.prototype = {
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -35363,63 +35336,21 @@ var Internal = Internal || {};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/*
|
||||||
*
|
* vim: ts=4:sw=4
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var util = (function() {
|
var util = (function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var StaticByteBufferProto = new dcodeIO.ByteBuffer().__proto__;
|
|
||||||
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
||||||
var StaticUint8ArrayProto = new Uint8Array().__proto__;
|
|
||||||
|
|
||||||
function stringObject(thing) {
|
|
||||||
if (typeof thing === 'string') {
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
if (thing === Object(thing)) {
|
|
||||||
if (thing.__proto__ == StaticUint8ArrayProto) {
|
|
||||||
return String.fromCharCode.apply(null, thing);
|
|
||||||
}
|
|
||||||
if (thing.__proto__ == StaticArrayBufferProto) {
|
|
||||||
return stringObject(new Uint8Array(thing));
|
|
||||||
}
|
|
||||||
if (thing.__proto__ == StaticByteBufferProto) {
|
|
||||||
return thing.toString('binary');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error('unsure how to stringify object of type ' + typeof thing);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toString: function(thing) {
|
toString: function(thing) {
|
||||||
if (typeof thing == 'string') {
|
if (typeof thing == 'string') {
|
||||||
return thing;
|
return thing;
|
||||||
} else if (util.isStringable(thing)) {
|
|
||||||
return util.stringObject(thing);
|
|
||||||
} else {
|
|
||||||
throw new Error("Unsure how to convert object to string from type " + typeof thing);
|
|
||||||
}
|
}
|
||||||
},
|
return new dcodeIO.ByteBuffer.wrap(thing).toString('binary');
|
||||||
stringObject: stringObject,
|
|
||||||
isStringable: function (thing) {
|
|
||||||
return (thing === Object(thing) &&
|
|
||||||
(thing.__proto__ == StaticArrayBufferProto ||
|
|
||||||
thing.__proto__ == StaticUint8ArrayProto ||
|
|
||||||
thing.__proto__ == StaticByteBufferProto));
|
|
||||||
},
|
},
|
||||||
toArrayBuffer: function(thing) {
|
toArrayBuffer: function(thing) {
|
||||||
if (thing === undefined) {
|
if (thing === undefined) {
|
||||||
|
@ -35429,42 +35360,23 @@ var util = (function() {
|
||||||
if (thing.__proto__ == StaticArrayBufferProto) {
|
if (thing.__proto__ == StaticArrayBufferProto) {
|
||||||
return thing;
|
return thing;
|
||||||
}
|
}
|
||||||
//TODO: Several more cases here...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thing instanceof Array) {
|
|
||||||
// Assuming Uint16Array from curve25519
|
|
||||||
//TODO: Move to convertToArrayBuffer
|
|
||||||
var res = new ArrayBuffer(thing.length * 2);
|
|
||||||
var uint = new Uint16Array(res);
|
|
||||||
for (var i = 0; i < thing.length; i++) {
|
|
||||||
uint[i] = thing[i];
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var str;
|
var str;
|
||||||
if (util.isStringable(thing)) {
|
if (typeof thing == "string") {
|
||||||
str = util.stringObject(thing);
|
|
||||||
} else if (typeof thing == "string") {
|
|
||||||
str = thing;
|
str = thing;
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Tried to convert a non-stringable thing of type " + typeof thing + " to an array buffer");
|
throw new Error("Tried to convert a non-string of type " + typeof thing + " to an array buffer");
|
||||||
}
|
}
|
||||||
var res = new ArrayBuffer(str.length);
|
return new dcodeIO.ByteBuffer.wrap(thing, 'binary').toArrayBuffer();
|
||||||
var uint = new Uint8Array(res);
|
|
||||||
for (var i = 0; i < str.length; i++) {
|
|
||||||
uint[i] = str.charCodeAt(i);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
},
|
||||||
isEqual: function(a, b) {
|
isEqual: function(a, b) {
|
||||||
// TODO: Special-case arraybuffers, etc
|
// TODO: Special-case arraybuffers, etc
|
||||||
if (a === undefined || b === undefined) {
|
if (a === undefined || b === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a = stringObject(a);
|
a = util.toString(a);
|
||||||
b = stringObject(b);
|
b = util.toString(b);
|
||||||
var maxLength = Math.max(a.length, b.length);
|
var maxLength = Math.max(a.length, b.length);
|
||||||
if (maxLength < 5) {
|
if (maxLength < 5) {
|
||||||
throw new Error("a/b compare too short");
|
throw new Error("a/b compare too short");
|
||||||
|
@ -35559,21 +35471,7 @@ Internal.protoText = function() {
|
||||||
|
|
||||||
return protoText;
|
return protoText;
|
||||||
}();
|
}();
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
Internal.protobuf = function() {
|
Internal.protobuf = function() {
|
||||||
|
@ -35581,7 +35479,7 @@ Internal.protobuf = function() {
|
||||||
|
|
||||||
function loadProtoBufs(filename) {
|
function loadProtoBufs(filename) {
|
||||||
return dcodeIO.ProtoBuf.loadProto(Internal.protoText['protos/' + filename]).build('textsecure');
|
return dcodeIO.ProtoBuf.loadProto(Internal.protoText['protos/' + filename]).build('textsecure');
|
||||||
};
|
}
|
||||||
|
|
||||||
var protocolMessages = loadProtoBufs('WhisperTextProtocol.proto');
|
var protocolMessages = loadProtoBufs('WhisperTextProtocol.proto');
|
||||||
|
|
||||||
|
@ -35591,44 +35489,50 @@ Internal.protobuf = function() {
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
/* vim: ts=4:sw=4
|
/* vim: ts=4:sw=4 */
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var Internal = Internal || {};
|
var Internal = Internal || {};
|
||||||
|
|
||||||
|
Internal.BaseKeyType = {
|
||||||
|
OURS: 1,
|
||||||
|
THEIRS: 2
|
||||||
|
};
|
||||||
|
Internal.ChainType = {
|
||||||
|
SENDING: 1,
|
||||||
|
RECEIVING: 2
|
||||||
|
};
|
||||||
|
|
||||||
Internal.SessionRecord = function() {
|
Internal.SessionRecord = function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
var MESSAGE_LOST_THRESHOLD_MS = 1000*60*60*24*7;
|
var MESSAGE_LOST_THRESHOLD_MS = 1000*60*60*24*7;
|
||||||
|
|
||||||
|
var StaticByteBufferProto = new dcodeIO.ByteBuffer().__proto__;
|
||||||
|
var StaticArrayBufferProto = new ArrayBuffer().__proto__;
|
||||||
|
var StaticUint8ArrayProto = new Uint8Array().__proto__;
|
||||||
|
|
||||||
|
function isStringable(thing) {
|
||||||
|
return (thing === Object(thing) &&
|
||||||
|
(thing.__proto__ == StaticArrayBufferProto ||
|
||||||
|
thing.__proto__ == StaticUint8ArrayProto ||
|
||||||
|
thing.__proto__ == StaticByteBufferProto));
|
||||||
|
}
|
||||||
function ensureStringed(thing) {
|
function ensureStringed(thing) {
|
||||||
if (typeof thing == "string" || typeof thing == "number" || typeof thing == "boolean") {
|
if (typeof thing == "string" || typeof thing == "number" || typeof thing == "boolean") {
|
||||||
return thing;
|
return thing;
|
||||||
} else if (util.isStringable(thing)) {
|
} else if (isStringable(thing)) {
|
||||||
return util.stringObject(thing);
|
return util.toString(thing);
|
||||||
} else if (thing instanceof Array) {
|
} else if (thing instanceof Array) {
|
||||||
var res = [];
|
var array = [];
|
||||||
for (var i = 0; i < thing.length; i++) {
|
for (var i = 0; i < thing.length; i++) {
|
||||||
res[i] = ensureStringed(thing[i]);
|
array[i] = ensureStringed(thing[i]);
|
||||||
}
|
}
|
||||||
return res;
|
return array;
|
||||||
} else if (thing === Object(thing)) {
|
} else if (thing === Object(thing)) {
|
||||||
var res = {};
|
var obj = {};
|
||||||
for (var key in thing) {
|
for (var key in thing) {
|
||||||
res[key] = ensureStringed(thing[key]);
|
obj[key] = ensureStringed(thing[key]);
|
||||||
}
|
}
|
||||||
return res;
|
return obj;
|
||||||
} else if (thing === null) {
|
} else if (thing === null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -35680,19 +35584,12 @@ Internal.SessionRecord = function() {
|
||||||
},
|
},
|
||||||
|
|
||||||
getSessionByBaseKey: function(baseKey) {
|
getSessionByBaseKey: function(baseKey) {
|
||||||
return this._sessions[util.toString(baseKey)];
|
var session = this._sessions[util.toString(baseKey)];
|
||||||
},
|
if (session && session.indexInfo.baseKeyType === Internal.BaseKeyType.OURS) {
|
||||||
getSessionOrIdentityKeyByBaseKey: function(baseKey) {
|
console.log("Tried to lookup a session using our basekey");
|
||||||
var preferredSession = this.getSessionByBaseKey(baseKey);
|
return undefined;
|
||||||
if (preferredSession !== undefined) {
|
|
||||||
return preferredSession;
|
|
||||||
}
|
}
|
||||||
|
return session;
|
||||||
if (this.identityKey !== undefined) {
|
|
||||||
return { indexInfo: { remoteIdentityKey: this.identityKey } };
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error("Datastore inconsistency: device was stored without identity key");
|
|
||||||
},
|
},
|
||||||
getSessionByRemoteEphemeralKey: function(remoteEphemeralKey) {
|
getSessionByRemoteEphemeralKey: function(remoteEphemeralKey) {
|
||||||
this.detectDuplicateOpenSessions();
|
this.detectDuplicateOpenSessions();
|
||||||
|
@ -35700,7 +35597,7 @@ Internal.SessionRecord = function() {
|
||||||
|
|
||||||
var searchKey = util.toString(remoteEphemeralKey);
|
var searchKey = util.toString(remoteEphemeralKey);
|
||||||
|
|
||||||
var openSession = undefined;
|
var openSession;
|
||||||
for (var key in sessions) {
|
for (var key in sessions) {
|
||||||
if (sessions[key].indexInfo.closed == -1) {
|
if (sessions[key].indexInfo.closed == -1) {
|
||||||
openSession = sessions[key];
|
openSession = sessions[key];
|
||||||
|
@ -35731,7 +35628,7 @@ Internal.SessionRecord = function() {
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
detectDuplicateOpenSessions: function() {
|
detectDuplicateOpenSessions: function() {
|
||||||
var openSession = undefined;
|
var openSession;
|
||||||
var sessions = this._sessions;
|
var sessions = this._sessions;
|
||||||
for (var key in sessions) {
|
for (var key in sessions) {
|
||||||
if (sessions[key].indexInfo.closed == -1) {
|
if (sessions[key].indexInfo.closed == -1) {
|
||||||
|
@ -35801,8 +35698,8 @@ Internal.SessionRecord = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete current root key and our ephemeral key pair to disallow ratchet stepping
|
// Delete current root key and our ephemeral key pair to disallow ratchet stepping
|
||||||
delete session.currentRatchet['rootKey'];
|
delete session.currentRatchet.rootKey;
|
||||||
delete session.currentRatchet['ephemeralKeyPair'];
|
delete session.currentRatchet.ephemeralKeyPair;
|
||||||
session.indexInfo.closed = Date.now();
|
session.indexInfo.closed = Date.now();
|
||||||
this.removeOldChains(session);
|
this.removeOldChains(session);
|
||||||
},
|
},
|
||||||
|
@ -36061,6 +35958,7 @@ SessionBuilder.prototype = {
|
||||||
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
|
||||||
if (isInitiator) {
|
if (isInitiator) {
|
||||||
session.indexInfo.baseKey = ourEphemeralKey.pubKey;
|
session.indexInfo.baseKey = ourEphemeralKey.pubKey;
|
||||||
|
session.indexInfo.baseKeyType = Internal.BaseKeyType.OURS;
|
||||||
return Internal.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
return Internal.crypto.createKeyPair().then(function(ourSendingEphemeralKey) {
|
||||||
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
session.currentRatchet.ephemeralKeyPair = ourSendingEphemeralKey;
|
||||||
return this.calculateSendingRatchet(session, theirSignedPubKey).then(function() {
|
return this.calculateSendingRatchet(session, theirSignedPubKey).then(function() {
|
||||||
|
@ -36069,6 +35967,7 @@ SessionBuilder.prototype = {
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
} else {
|
} else {
|
||||||
session.indexInfo.baseKey = theirEphemeralPubKey;
|
session.indexInfo.baseKey = theirEphemeralPubKey;
|
||||||
|
session.indexInfo.baseKeyType = Internal.BaseKeyType.THEIRS;
|
||||||
session.currentRatchet.ephemeralKeyPair = ourSignedKey;
|
session.currentRatchet.ephemeralKeyPair = ourSignedKey;
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
@ -36087,7 +35986,8 @@ SessionBuilder.prototype = {
|
||||||
}).then(function(masterKey) {
|
}).then(function(masterKey) {
|
||||||
session[util.toString(ratchet.ephemeralKeyPair.pubKey)] = {
|
session[util.toString(ratchet.ephemeralKeyPair.pubKey)] = {
|
||||||
messageKeys : {},
|
messageKeys : {},
|
||||||
chainKey : { counter : -1, key : masterKey[1] }
|
chainKey : { counter : -1, key : masterKey[1] },
|
||||||
|
chainType : Internal.ChainType.SENDING
|
||||||
};
|
};
|
||||||
ratchet.rootKey = masterKey[0];
|
ratchet.rootKey = masterKey[0];
|
||||||
});
|
});
|
||||||
|
@ -36152,6 +36052,9 @@ SessionCipher.prototype = {
|
||||||
session.currentRatchet.ephemeralKeyPair.pubKey
|
session.currentRatchet.ephemeralKeyPair.pubKey
|
||||||
);
|
);
|
||||||
chain = session[util.toString(msg.ephemeralKey)];
|
chain = session[util.toString(msg.ephemeralKey)];
|
||||||
|
if (chain.chainType === Internal.ChainType.RECEIVING) {
|
||||||
|
throw new Error("Tried to encrypt on a receiving chain");
|
||||||
|
}
|
||||||
|
|
||||||
return this.fillMessageKeys(chain, chain.chainKey.counter + 1);
|
return this.fillMessageKeys(chain, chain.chainKey.counter + 1);
|
||||||
}.bind(this)).then(function() {
|
}.bind(this)).then(function() {
|
||||||
|
@ -36210,7 +36113,7 @@ SessionCipher.prototype = {
|
||||||
var messageLengthWithTerminator = messageLength + 1;
|
var messageLengthWithTerminator = messageLength + 1;
|
||||||
var messagePartCount = Math.floor(messageLengthWithTerminator / 160);
|
var messagePartCount = Math.floor(messageLengthWithTerminator / 160);
|
||||||
|
|
||||||
if (messageLengthWithTerminator % 160 != 0) {
|
if (messageLengthWithTerminator % 160 !== 0) {
|
||||||
messagePartCount++;
|
messagePartCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36298,6 +36201,9 @@ SessionCipher.prototype = {
|
||||||
|
|
||||||
return this.maybeStepRatchet(session, remoteEphemeralKey, message.previousCounter).then(function() {
|
return this.maybeStepRatchet(session, remoteEphemeralKey, message.previousCounter).then(function() {
|
||||||
var chain = session[util.toString(message.ephemeralKey)];
|
var chain = session[util.toString(message.ephemeralKey)];
|
||||||
|
if (chain.chainType === Internal.ChainType.SENDING) {
|
||||||
|
throw new Error("Tried to decrypt on a sending chain");
|
||||||
|
}
|
||||||
|
|
||||||
return this.fillMessageKeys(chain, message.counter).then(function() {
|
return this.fillMessageKeys(chain, message.counter).then(function() {
|
||||||
var messageKey = chain.messageKeys[message.counter];
|
var messageKey = chain.messageKeys[message.counter];
|
||||||
|
@ -36331,12 +36237,12 @@ SessionCipher.prototype = {
|
||||||
plaintext.set(paddedPlaintext.subarray(0, i));
|
plaintext.set(paddedPlaintext.subarray(0, i));
|
||||||
plaintext = plaintext.buffer;
|
plaintext = plaintext.buffer;
|
||||||
break;
|
break;
|
||||||
} else if (paddedPlaintext[i] != 0x00) {
|
} else if (paddedPlaintext[i] !== 0x00) {
|
||||||
throw new Error('Invalid padding');
|
throw new Error('Invalid padding');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete session['pendingPreKey'];
|
delete session.pendingPreKey;
|
||||||
return plaintext;
|
return plaintext;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -36417,7 +36323,8 @@ SessionCipher.prototype = {
|
||||||
}
|
}
|
||||||
session[util.toString(ephemeralPublicKey)] = {
|
session[util.toString(ephemeralPublicKey)] = {
|
||||||
messageKeys: {},
|
messageKeys: {},
|
||||||
chainKey: { counter: -1, key: masterKey[1] }
|
chainKey: { counter: -1, key: masterKey[1] },
|
||||||
|
chainType: sending ? Internal.ChainType.SENDING : Internal.ChainType.RECEIVING
|
||||||
};
|
};
|
||||||
ratchet.rootKey = masterKey[0];
|
ratchet.rootKey = masterKey[0];
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue