textsecure.protos

This commit is contained in:
Matt Corallo 2014-05-21 15:04:05 -04:00
parent 665f0ef00a
commit 9aae93fc99
4 changed files with 63 additions and 53 deletions

View file

@ -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");

View file

@ -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 = {};
self.IncomingPushMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.IncomingPushMessageSignal");
self.decodeIncomingPushMessageProtobuf = function(string) {
return IncomingPushMessageProtobuf.decode(btoa(string)); return IncomingPushMessageProtobuf.decode(btoa(string));
} }
var PushMessageContentProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.PushMessageContent"); self.PushMessageContentProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.PushMessageContent");
function decodePushMessageContentProtobuf(string) { self.decodePushMessageContentProtobuf = function(string) {
return PushMessageContentProtobuf.decode(btoa(string)); return PushMessageContentProtobuf.decode(btoa(string));
} }
var WhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.WhisperMessage"); self.WhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.WhisperMessage");
function decodeWhisperMessageProtobuf(string) { self.decodeWhisperMessageProtobuf = function(string) {
return WhisperMessageProtobuf.decode(btoa(string)); return WhisperMessageProtobuf.decode(btoa(string));
} }
var PreKeyWhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.PreKeyWhisperMessage"); self.PreKeyWhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.PreKeyWhisperMessage");
function decodePreKeyWhisperMessageProtobuf(string) { self.decodePreKeyWhisperMessageProtobuf = function(string) {
return PreKeyWhisperMessageProtobuf.decode(btoa(string)); return PreKeyWhisperMessageProtobuf.decode(btoa(string));
} }
var KeyExchangeMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.KeyExchangeMessage"); self.KeyExchangeMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.KeyExchangeMessage");
function decodeKeyExchangeMessageProtobuf(string) { self.decodeKeyExchangeMessageProtobuf = function(string) {
return KeyExchangeMessageProtobuf.decode(btoa(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);

View file

@ -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')});
} }
}); });

View file

@ -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;
} }