|
|
|
@ -349,20 +349,8 @@ window.textsecure.protocol = function() {
|
|
|
|
|
crypto_storage.saveSession(encodedNumber, session);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var initSessionFromPreKeyWhisperMessage;
|
|
|
|
|
var decryptWhisperMessage;
|
|
|
|
|
var handlePreKeyWhisperMessage = function(from, encodedMessage) {
|
|
|
|
|
var preKeyProto = textsecure.protobuf.PreKeyWhisperMessage.decode(encodedMessage, 'binary');
|
|
|
|
|
return initSessionFromPreKeyWhisperMessage(from, preKeyProto).then(function(sessions) {
|
|
|
|
|
return decryptWhisperMessage(from, getString(preKeyProto.message), sessions[0], preKeyProto.registrationId).then(function(result) {
|
|
|
|
|
if (sessions[1] !== undefined)
|
|
|
|
|
sessions[1]();
|
|
|
|
|
return result;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var wipeIdentityAndTryMessageAgain = function(from, encodedMessage, message_id) {
|
|
|
|
|
//TODO: Rewrite this!
|
|
|
|
|
/*var wipeIdentityAndTryMessageAgain = function(from, encodedMessage, message_id) {
|
|
|
|
|
// Wipe identity key!
|
|
|
|
|
textsecure.storage.removeEncrypted("devices" + from.split('.')[0]);
|
|
|
|
|
return handlePreKeyWhisperMessage(from, encodedMessage).then(
|
|
|
|
@ -374,9 +362,9 @@ window.textsecure.protocol = function() {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
textsecure.replay.registerFunction(wipeIdentityAndTryMessageAgain, textsecure.replay.Type.INIT_SESSION);
|
|
|
|
|
textsecure.replay.registerFunction(wipeIdentityAndTryMessageAgain, textsecure.replay.Type.INIT_SESSION);*/
|
|
|
|
|
|
|
|
|
|
initSessionFromPreKeyWhisperMessage = function(encodedNumber, message) {
|
|
|
|
|
var initSessionFromPreKeyWhisperMessage = function(encodedNumber, message) {
|
|
|
|
|
var preKeyPair = crypto_storage.getStoredKeyPair("preKey" + message.preKeyId);
|
|
|
|
|
var signedPreKeyPair = crypto_storage.getStoredKeyPair("signedKey" + message.signedPreKeyId);
|
|
|
|
|
|
|
|
|
@ -478,15 +466,18 @@ window.textsecure.protocol = function() {
|
|
|
|
|
return finish();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// returns decrypted protobuf
|
|
|
|
|
decryptWhisperMessage = function(encodedNumber, messageBytes, session, registrationId) {
|
|
|
|
|
/*************************
|
|
|
|
|
*** Public crypto API ***
|
|
|
|
|
*************************/
|
|
|
|
|
// returns decrypted plaintext
|
|
|
|
|
self.decryptWhisperMessage = function(encodedNumber, messageBytes, session, registrationId) {
|
|
|
|
|
if (messageBytes[0] != String.fromCharCode((3 << 4) | 3))
|
|
|
|
|
throw new Error("Bad version number on WhisperMessage");
|
|
|
|
|
|
|
|
|
|
var messageProto = messageBytes.substring(1, messageBytes.length - 8);
|
|
|
|
|
var mac = messageBytes.substring(messageBytes.length - 8, messageBytes.length);
|
|
|
|
|
|
|
|
|
|
var message = textsecure.protobuf.WhisperMessage.decode(messageProto, 'binary');
|
|
|
|
|
var message = axolotl.protobuf.WhisperMessage.decode(messageProto, 'binary');
|
|
|
|
|
var remoteEphemeralKey = toArrayBuffer(message.ephemeralKey);
|
|
|
|
|
|
|
|
|
|
if (session === undefined) {
|
|
|
|
@ -526,17 +517,9 @@ window.textsecure.protocol = function() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete session['pendingPreKey'];
|
|
|
|
|
|
|
|
|
|
var finalMessage = textsecure.protobuf.PushMessageContent.decode(plaintext);
|
|
|
|
|
|
|
|
|
|
if ((finalMessage.flags & textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
|
|
|
|
|
== textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
|
|
|
|
|
closeSession(session, true);
|
|
|
|
|
|
|
|
|
|
removeOldChains(session);
|
|
|
|
|
|
|
|
|
|
crypto_storage.saveSession(encodedNumber, session, registrationId);
|
|
|
|
|
return finalMessage;
|
|
|
|
|
return [plaintext, session];
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
@ -544,9 +527,18 @@ window.textsecure.protocol = function() {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*************************
|
|
|
|
|
*** Public crypto API ***
|
|
|
|
|
*************************/
|
|
|
|
|
// Inits a session (maybe) and then decrypts the message
|
|
|
|
|
self.handlePreKeyWhisperMessage = function(from, encodedMessage) {
|
|
|
|
|
var preKeyProto = axolotl.protobuf.PreKeyWhisperMessage.decode(encodedMessage, 'binary');
|
|
|
|
|
return initSessionFromPreKeyWhisperMessage(from, preKeyProto).then(function(sessions) {
|
|
|
|
|
return self.decryptWhisperMessage(from, getString(preKeyProto.message), sessions[0], preKeyProto.registrationId).then(function(result) {
|
|
|
|
|
if (sessions[1] !== undefined)
|
|
|
|
|
sessions[1]();
|
|
|
|
|
return result;
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Decrypts message into a raw string
|
|
|
|
|
self.decryptWebsocketMessage = function(message) {
|
|
|
|
|
var signaling_key = textsecure.storage.getEncrypted("signaling_key"); //TODO: in crypto_storage
|
|
|
|
@ -599,31 +591,12 @@ window.textsecure.protocol = function() {
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.handleIncomingPushMessageProto = function(proto) {
|
|
|
|
|
switch(proto.type) {
|
|
|
|
|
case textsecure.protobuf.IncomingPushMessageSignal.Type.PLAINTEXT:
|
|
|
|
|
return Promise.resolve(textsecure.protobuf.PushMessageContent.decode(proto.message));
|
|
|
|
|
case textsecure.protobuf.IncomingPushMessageSignal.Type.CIPHERTEXT:
|
|
|
|
|
var from = proto.source + "." + (proto.sourceDevice == null ? 0 : proto.sourceDevice);
|
|
|
|
|
return decryptWhisperMessage(from, getString(proto.message));
|
|
|
|
|
case textsecure.protobuf.IncomingPushMessageSignal.Type.PREKEY_BUNDLE:
|
|
|
|
|
if (proto.message.readUint8() != ((3 << 4) | 3))
|
|
|
|
|
throw new Error("Bad version byte");
|
|
|
|
|
var from = proto.source + "." + (proto.sourceDevice == null ? 0 : proto.sourceDevice);
|
|
|
|
|
return handlePreKeyWhisperMessage(from, getString(proto.message));
|
|
|
|
|
case textsecure.protobuf.IncomingPushMessageSignal.Type.RECEIPT:
|
|
|
|
|
return Promise.resolve(null);
|
|
|
|
|
default:
|
|
|
|
|
return new Promise(function(resolve, reject) { reject(new Error("Unknown message type")); });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// return Promise(encoded [PreKey]WhisperMessage)
|
|
|
|
|
self.encryptMessageFor = function(deviceObject, pushMessageContent) {
|
|
|
|
|
var session = crypto_storage.getOpenSession(deviceObject.encodedNumber);
|
|
|
|
|
|
|
|
|
|
var doEncryptPushMessageContent = function() {
|
|
|
|
|
var msg = new textsecure.protobuf.WhisperMessage();
|
|
|
|
|
var msg = new axolotl.protobuf.WhisperMessage();
|
|
|
|
|
var plaintext = toArrayBuffer(pushMessageContent.encode());
|
|
|
|
|
|
|
|
|
|
var paddedPlaintext = new Uint8Array(Math.ceil((plaintext.byteLength + 1) / 160.0) * 160 - 1);
|
|
|
|
@ -672,7 +645,7 @@ window.textsecure.protocol = function() {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var preKeyMsg = new textsecure.protobuf.PreKeyWhisperMessage();
|
|
|
|
|
var preKeyMsg = new axolotl.protobuf.PreKeyWhisperMessage();
|
|
|
|
|
preKeyMsg.identityKey = toArrayBuffer(crypto_storage.getIdentityKey().pubKey);
|
|
|
|
|
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
|
|
|
|
|
|
|
|
|