textsecure.protos
This commit is contained in:
parent
665f0ef00a
commit
9aae93fc99
4 changed files with 63 additions and 53 deletions
12
js/crypto.js
12
js/crypto.js
|
@ -523,7 +523,7 @@ window.textsecure.crypto = new function() {
|
||||||
var messageProto = messageBytes.substring(1, messageBytes.length - 8);
|
var messageProto = messageBytes.substring(1, messageBytes.length - 8);
|
||||||
var mac = messageBytes.substring(messageBytes.length - 8, messageBytes.length);
|
var mac = messageBytes.substring(messageBytes.length - 8, messageBytes.length);
|
||||||
|
|
||||||
var message = decodeWhisperMessageProtobuf(messageProto);
|
var message = textsecure.protos.decodeWhisperMessageProtobuf(messageProto);
|
||||||
var remoteEphemeralKey = toArrayBuffer(message.ephemeralKey);
|
var remoteEphemeralKey = toArrayBuffer(message.ephemeralKey);
|
||||||
|
|
||||||
if (session === undefined) {
|
if (session === undefined) {
|
||||||
|
@ -547,7 +547,7 @@ window.textsecure.crypto = new function() {
|
||||||
removeOldChains(session);
|
removeOldChains(session);
|
||||||
delete session['pendingPreKey'];
|
delete session['pendingPreKey'];
|
||||||
|
|
||||||
var finalMessage = decodePushMessageContentProtobuf(getString(plaintext));
|
var finalMessage = textsecure.protos.decodePushMessageContentProtobuf(getString(plaintext));
|
||||||
|
|
||||||
if ((finalMessage.flags & 1) == 1) // END_SESSION
|
if ((finalMessage.flags & 1) == 1) // END_SESSION
|
||||||
closeSession(session);
|
closeSession(session);
|
||||||
|
@ -601,7 +601,7 @@ window.textsecure.crypto = new function() {
|
||||||
self.handleIncomingPushMessageProto = function(proto) {
|
self.handleIncomingPushMessageProto = function(proto) {
|
||||||
switch(proto.type) {
|
switch(proto.type) {
|
||||||
case 0: //TYPE_MESSAGE_PLAINTEXT
|
case 0: //TYPE_MESSAGE_PLAINTEXT
|
||||||
return Promise.resolve(decodePushMessageContentProtobuf(getString(proto.message)));
|
return Promise.resolve(textsecure.protos.decodePushMessageContentProtobuf(getString(proto.message)));
|
||||||
case 1: //TYPE_MESSAGE_CIPHERTEXT
|
case 1: //TYPE_MESSAGE_CIPHERTEXT
|
||||||
return decryptWhisperMessage(proto.source, getString(proto.message)).then(function(result) {
|
return decryptWhisperMessage(proto.source, getString(proto.message)).then(function(result) {
|
||||||
return {message:result, pushMessage: proto};
|
return {message:result, pushMessage: proto};
|
||||||
|
@ -609,7 +609,7 @@ window.textsecure.crypto = new function() {
|
||||||
case 3: //TYPE_MESSAGE_PREKEY_BUNDLE
|
case 3: //TYPE_MESSAGE_PREKEY_BUNDLE
|
||||||
if (proto.message.readUint8() != (2 << 4 | 2))
|
if (proto.message.readUint8() != (2 << 4 | 2))
|
||||||
throw new Error("Bad version byte");
|
throw new Error("Bad version byte");
|
||||||
var preKeyProto = decodePreKeyWhisperMessageProtobuf(getString(proto.message));
|
var preKeyProto = textsecure.protos.decodePreKeyWhisperMessageProtobuf(getString(proto.message));
|
||||||
return initSessionFromPreKeyWhisperMessage(proto.source, preKeyProto).then(function(sessions) {
|
return initSessionFromPreKeyWhisperMessage(proto.source, preKeyProto).then(function(sessions) {
|
||||||
return decryptWhisperMessage(proto.source, getString(preKeyProto.message), sessions[0]).then(function(result) {
|
return decryptWhisperMessage(proto.source, getString(preKeyProto.message), sessions[0]).then(function(result) {
|
||||||
if (sessions[1] !== undefined)
|
if (sessions[1] !== undefined)
|
||||||
|
@ -625,7 +625,7 @@ window.textsecure.crypto = new function() {
|
||||||
var session = crypto_storage.getOpenSession(deviceObject.encodedNumber);
|
var session = crypto_storage.getOpenSession(deviceObject.encodedNumber);
|
||||||
|
|
||||||
var doEncryptPushMessageContent = function() {
|
var doEncryptPushMessageContent = function() {
|
||||||
var msg = new WhisperMessageProtobuf();
|
var msg = new textsecure.protos.WhisperMessageProtobuf();
|
||||||
var plaintext = toArrayBuffer(pushMessageContent.encode());
|
var plaintext = toArrayBuffer(pushMessageContent.encode());
|
||||||
|
|
||||||
msg.ephemeralKey = toArrayBuffer(session.currentRatchet.ephemeralKeyPair.pubKey);
|
msg.ephemeralKey = toArrayBuffer(session.currentRatchet.ephemeralKeyPair.pubKey);
|
||||||
|
@ -655,7 +655,7 @@ window.textsecure.crypto = new function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var preKeyMsg = new PreKeyWhisperMessageProtobuf();
|
var preKeyMsg = new textsecure.protos.PreKeyWhisperMessageProtobuf();
|
||||||
preKeyMsg.identityKey = toArrayBuffer(crypto_storage.getStoredPubKey("identityKey"));
|
preKeyMsg.identityKey = toArrayBuffer(crypto_storage.getStoredPubKey("identityKey"));
|
||||||
preKeyMsg.preKeyId = deviceObject.preKeyId;
|
preKeyMsg.preKeyId = deviceObject.preKeyId;
|
||||||
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
|
||||||
|
|
|
@ -152,27 +152,6 @@ function toArrayBuffer(thing) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureStringed(thing) {
|
|
||||||
if (getStringable(thing))
|
|
||||||
return getString(thing);
|
|
||||||
else if (thing instanceof Array) {
|
|
||||||
var res = [];
|
|
||||||
for (var i = 0; i < thing.length; i++)
|
|
||||||
res[i] = ensureStringed(thing[i]);
|
|
||||||
return res;
|
|
||||||
} else if (thing === Object(thing)) {
|
|
||||||
var res = {};
|
|
||||||
for (key in thing)
|
|
||||||
res[key] = ensureStringed(thing[key]);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
throw new Error("unsure of how to jsonify object of type " + typeof thing);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function jsonThing(thing) {
|
|
||||||
return JSON.stringify(ensureStringed(thing));
|
|
||||||
}
|
|
||||||
|
|
||||||
function base64ToArrayBuffer(string) {
|
function base64ToArrayBuffer(string) {
|
||||||
return base64DecToArr(string);
|
return base64DecToArr(string);
|
||||||
|
@ -180,30 +159,36 @@ function base64ToArrayBuffer(string) {
|
||||||
|
|
||||||
// Protobuf decoding
|
// Protobuf decoding
|
||||||
//TODO: throw on missing fields everywhere
|
//TODO: throw on missing fields everywhere
|
||||||
var IncomingPushMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.IncomingPushMessageSignal");
|
window.textsecure.protos = function() {
|
||||||
function decodeIncomingPushMessageProtobuf(string) {
|
var self = {};
|
||||||
return IncomingPushMessageProtobuf.decode(btoa(string));
|
|
||||||
}
|
|
||||||
|
|
||||||
var PushMessageContentProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.PushMessageContent");
|
self.IncomingPushMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.IncomingPushMessageSignal");
|
||||||
function decodePushMessageContentProtobuf(string) {
|
self.decodeIncomingPushMessageProtobuf = function(string) {
|
||||||
return PushMessageContentProtobuf.decode(btoa(string));
|
return IncomingPushMessageProtobuf.decode(btoa(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
var WhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.WhisperMessage");
|
self.PushMessageContentProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.PushMessageContent");
|
||||||
function decodeWhisperMessageProtobuf(string) {
|
self.decodePushMessageContentProtobuf = function(string) {
|
||||||
return WhisperMessageProtobuf.decode(btoa(string));
|
return PushMessageContentProtobuf.decode(btoa(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
var PreKeyWhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.PreKeyWhisperMessage");
|
self.WhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.WhisperMessage");
|
||||||
function decodePreKeyWhisperMessageProtobuf(string) {
|
self.decodeWhisperMessageProtobuf = function(string) {
|
||||||
return PreKeyWhisperMessageProtobuf.decode(btoa(string));
|
return WhisperMessageProtobuf.decode(btoa(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
var KeyExchangeMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.KeyExchangeMessage");
|
self.PreKeyWhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.PreKeyWhisperMessage");
|
||||||
function decodeKeyExchangeMessageProtobuf(string) {
|
self.decodePreKeyWhisperMessageProtobuf = function(string) {
|
||||||
return KeyExchangeMessageProtobuf.decode(btoa(string));
|
return PreKeyWhisperMessageProtobuf.decode(btoa(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.KeyExchangeMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.KeyExchangeMessage");
|
||||||
|
self.decodeKeyExchangeMessageProtobuf = function(string) {
|
||||||
|
return KeyExchangeMessageProtobuf.decode(btoa(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}();
|
||||||
|
|
||||||
// Number formatting
|
// Number formatting
|
||||||
function getNumberFromString(string) {
|
function getNumberFromString(string) {
|
||||||
|
@ -232,6 +217,31 @@ function verifyNumber(string) {
|
||||||
window.textsecure.storage = function() {
|
window.textsecure.storage = function() {
|
||||||
var self = {};
|
var self = {};
|
||||||
|
|
||||||
|
/****************************
|
||||||
|
*** Conversion Utilities ***
|
||||||
|
****************************/
|
||||||
|
function ensureStringed(thing) {
|
||||||
|
if (getStringable(thing))
|
||||||
|
return getString(thing);
|
||||||
|
else if (thing instanceof Array) {
|
||||||
|
var res = [];
|
||||||
|
for (var i = 0; i < thing.length; i++)
|
||||||
|
res[i] = ensureStringed(thing[i]);
|
||||||
|
return res;
|
||||||
|
} else if (thing === Object(thing)) {
|
||||||
|
var res = {};
|
||||||
|
for (key in thing)
|
||||||
|
res[key] = ensureStringed(thing[key]);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
throw new Error("unsure of how to jsonify object of type " + typeof thing);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsonThing(thing) {
|
||||||
|
return JSON.stringify(ensureStringed(thing));
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
*** Base Storage Routines ***
|
*** Base Storage Routines ***
|
||||||
*****************************/
|
*****************************/
|
||||||
|
@ -426,7 +436,7 @@ window.textsecure.subscribeToPush = function() {
|
||||||
console.log("Got pong message");
|
console.log("Got pong message");
|
||||||
} else if (message.type === undefined && message.id !== undefined) {
|
} else if (message.type === undefined && message.id !== undefined) {
|
||||||
textsecure.crypto.decryptWebsocketMessage(message.message).then(function(plaintext) {
|
textsecure.crypto.decryptWebsocketMessage(message.message).then(function(plaintext) {
|
||||||
var proto = decodeIncomingPushMessageProtobuf(getString(plaintext));
|
var proto = textsecure.protos.decodeIncomingPushMessageProtobuf(getString(plaintext));
|
||||||
// After this point, a) decoding errors are not the server's fault, and
|
// After this point, a) decoding errors are not the server's fault, and
|
||||||
// b) we should handle them gracefully and tell the user they received an invalid message
|
// b) we should handle them gracefully and tell the user they received an invalid message
|
||||||
console.log("Successfully decoded message with id: " + message.id);
|
console.log("Successfully decoded message with id: " + message.id);
|
||||||
|
|
|
@ -5,7 +5,7 @@ var Whisper = Whisper || {};
|
||||||
|
|
||||||
var Message = Backbone.Model.extend({
|
var Message = Backbone.Model.extend({
|
||||||
toProto: function() {
|
toProto: function() {
|
||||||
return new PushMessageContentProtobuf({body: this.get('body')});
|
return new textsecure.protos.PushMessageContentProtobuf({body: this.get('body')});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -336,11 +336,11 @@ textsecure.registerOnLoadFunction(function() {
|
||||||
if (data.newEphemeralKey !== undefined)
|
if (data.newEphemeralKey !== undefined)
|
||||||
privKeyQueue.push(data.newEphemeralKey);
|
privKeyQueue.push(data.newEphemeralKey);
|
||||||
|
|
||||||
var message = new IncomingPushMessageProtobuf();
|
var message = new textsecure.protos.IncomingPushMessageProtobuf();
|
||||||
message.type = data.type;
|
message.type = data.type;
|
||||||
message.source = remoteDevice.encodedNumber;
|
message.source = remoteDevice.encodedNumber;
|
||||||
message.message = data.message;
|
message.message = data.message;
|
||||||
return textsecure.crypto.handleIncomingPushMessageProto(decodeIncomingPushMessageProtobuf(getString(message.encode()))).then(function(res) {
|
return textsecure.crypto.handleIncomingPushMessageProto(textsecure.protos.decodeIncomingPushMessageProtobuf(getString(message.encode()))).then(function(res) {
|
||||||
return res.message.body == data.expectedSmsText;
|
return res.message.body == data.expectedSmsText;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -373,11 +373,11 @@ textsecure.registerOnLoadFunction(function() {
|
||||||
//XXX: This should be all we do: stepDone(getString(data.expectedCiphertext) == getString(res.body));
|
//XXX: This should be all we do: stepDone(getString(data.expectedCiphertext) == getString(res.body));
|
||||||
if (res.type == 1) { //XXX: This should be used for everything...
|
if (res.type == 1) { //XXX: This should be used for everything...
|
||||||
var expectedString = getString(data.expectedCiphertext);
|
var expectedString = getString(data.expectedCiphertext);
|
||||||
var decoded = decodeWhisperMessageProtobuf(expectedString.substring(1, expectedString.length - 8));
|
var decoded = textsecure.protos.decodeWhisperMessageProtobuf(expectedString.substring(1, expectedString.length - 8));
|
||||||
var result = getString(res.body);
|
var result = getString(res.body);
|
||||||
return getString(decoded.encode()) == result.substring(1, result.length - 8);
|
return getString(decoded.encode()) == result.substring(1, result.length - 8);
|
||||||
} else {
|
} else {
|
||||||
var decoded = decodePreKeyWhisperMessageProtobuf(getString(data.expectedCiphertext).substr(1));
|
var decoded = textsecure.protos.decodePreKeyWhisperMessageProtobuf(getString(data.expectedCiphertext).substr(1));
|
||||||
var result = getString(res.body).substring(1);
|
var result = getString(res.body).substring(1);
|
||||||
return getString(decoded.encode()) == result;
|
return getString(decoded.encode()) == result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue