diff --git a/background.html b/background.html
index 2d90e6558..b0e186ba0 100644
--- a/background.html
+++ b/background.html
@@ -27,6 +27,7 @@
+
diff --git a/index.html b/index.html
index da54265b3..6b286fc62 100644
--- a/index.html
+++ b/index.html
@@ -129,6 +129,7 @@
+
diff --git a/js/crypto.js b/js/crypto.js
index 7672ecf00..445bcaa2f 100644
--- a/js/crypto.js
+++ b/js/crypto.js
@@ -536,7 +536,7 @@ window.textsecure.crypto = function() {
var initSessionFromPreKeyWhisperMessage;
var decryptWhisperMessage;
var handlePreKeyWhisperMessage = function(from, encodedMessage) {
- var preKeyProto = textsecure.protos.decodePreKeyWhisperMessageProtobuf(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)
@@ -662,7 +662,7 @@ window.textsecure.crypto = function() {
var messageProto = messageBytes.substring(1, messageBytes.length - 8);
var mac = messageBytes.substring(messageBytes.length - 8, messageBytes.length);
- var message = textsecure.protos.decodeWhisperMessageProtobuf(messageProto);
+ var message = textsecure.protobuf.WhisperMessage.decode(messageProto, 'binary');
var remoteEphemeralKey = toArrayBuffer(message.ephemeralKey);
if (session === undefined) {
@@ -704,10 +704,10 @@ window.textsecure.crypto = function() {
delete session['pendingPreKey'];
- var finalMessage = textsecure.protos.decodePushMessageContentProtobuf(getString(plaintext));
+ var finalMessage = textsecure.protobuf.PushMessageContent.decode(plaintext);
- if ((finalMessage.flags & textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION)
- == textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION)
+ if ((finalMessage.flags & textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
+ == textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
closeSession(session, true);
removeOldChains(session);
@@ -778,17 +778,17 @@ window.textsecure.crypto = function() {
self.handleIncomingPushMessageProto = function(proto) {
switch(proto.type) {
- case textsecure.protos.IncomingPushMessageProtobuf.Type.PLAINTEXT:
- return Promise.resolve(textsecure.protos.decodePushMessageContentProtobuf(getString(proto.message)));
- case textsecure.protos.IncomingPushMessageProtobuf.Type.CIPHERTEXT:
+ 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.protos.IncomingPushMessageProtobuf.Type.PREKEY_BUNDLE:
+ 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.protos.IncomingPushMessageProtobuf.Type.RECEIPT:
+ case textsecure.protobuf.IncomingPushMessageSignal.Type.RECEIPT:
return Promise.resolve(null);
default:
return new Promise(function(resolve, reject) { reject(new Error("Unknown message type")); });
@@ -800,7 +800,7 @@ window.textsecure.crypto = function() {
var session = crypto_storage.getOpenSession(deviceObject.encodedNumber);
var doEncryptPushMessageContent = function() {
- var msg = new textsecure.protos.WhisperMessageProtobuf();
+ var msg = new textsecure.protobuf.WhisperMessage();
var plaintext = toArrayBuffer(pushMessageContent.encode());
var paddedPlaintext = new Uint8Array(Math.ceil((plaintext.byteLength + 1) / 160.0) * 160);
@@ -850,7 +850,7 @@ window.textsecure.crypto = function() {
});
}
- var preKeyMsg = new textsecure.protos.PreKeyWhisperMessageProtobuf();
+ var preKeyMsg = new textsecure.protobuf.PreKeyWhisperMessage();
preKeyMsg.identityKey = toArrayBuffer(crypto_storage.getIdentityKey().pubKey);
preKeyMsg.registrationId = textsecure.storage.getUnencrypted("registrationId");
@@ -957,7 +957,7 @@ window.textsecure.crypto = function() {
return verifyMAC(ivAndCiphertext, ecRes[1], mac).then(function() {
window.crypto.subtle.decrypt({name: "AES-CBC", iv: iv}, ecRes[0], ciphertext).then(function(plaintext) {
- var identityKeyMsg = textsecure.protos.decodeIdentityKeyProtobuf(getString(plaintext));
+ var identityKeyMsg = textsecure.protobuf.IdentityKey.decode(plaintext);
privToPub(toArrayBuffer(identityKeyMsg.identityKey)).then(function(identityKeyPair) {
crypto_storage.putKeyPair("identityKey", identityKeyPair);
diff --git a/js/helpers.js b/js/helpers.js
index f9ff31eeb..b15e04810 100644
--- a/js/helpers.js
+++ b/js/helpers.js
@@ -167,49 +167,6 @@ function base64ToArrayBuffer(string) {
return base64DecToArr(string);
}
-// Protobuf decoding
-//TODO: throw on missing fields everywhere
-window.textsecure.protos = function() {
- var self = {};
-
- self.IncomingPushMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.IncomingPushMessageSignal");
- self.decodeIncomingPushMessageProtobuf = function(string) {
- return self.IncomingPushMessageProtobuf.decode(btoa(string));
- }
-
- self.PushMessageContentProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/IncomingPushMessageSignal.proto").build("textsecure.PushMessageContent");
- self.decodePushMessageContentProtobuf = function(string) {
- return self.PushMessageContentProtobuf.decode(btoa(string));
- }
-
- self.WhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.WhisperMessage");
- self.decodeWhisperMessageProtobuf = function(string) {
- return self.WhisperMessageProtobuf.decode(btoa(string));
- }
-
- self.PreKeyWhisperMessageProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/WhisperTextProtocol.proto").build("textsecure.PreKeyWhisperMessage");
- self.decodePreKeyWhisperMessageProtobuf = function(string) {
- return self.PreKeyWhisperMessageProtobuf.decode(btoa(string));
- }
-
- self.DeviceInitProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/DeviceMessages.proto").build("textsecure.DeviceInit");
- self.decodeDeviceInitProtobuf = function(string) {
- return self.DeviceInitProtobuf.decode(btoa(string));
- }
-
- self.IdentityKeyProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/DeviceMessages.proto").build("textsecure.IdentityKey");
- self.decodeIdentityKeyProtobuf = function(string) {
- return self.IdentityKeyProtobuf.decode(btoa(string));
- }
-
- self.DeviceControlProtobuf = dcodeIO.ProtoBuf.loadProtoFile("protos/DeviceMessages.proto").build("textsecure.DeviceControl");
- self.decodeDeviceControlProtobuf = function(string) {
- return self.DeviceControlProtobuf.decode(btoa(string));
- }
-
- return self;
-}();
-
// Number formatting utils
window.textsecure.utils = function() {
var self = {};
@@ -611,7 +568,7 @@ window.textsecure.subscribeToPush = function(message_callback) {
socket.onmessage = function(message) {
textsecure.crypto.decryptWebsocketMessage(message.message).then(function(plaintext) {
- var proto = textsecure.protos.decodeIncomingPushMessageProtobuf(getString(plaintext));
+ var proto = textsecure.protobuf.IncomingPushMessageSignal.decode(plaintext);
// 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
console.log("Successfully decoded message with id: " + message.id);
@@ -629,8 +586,8 @@ window.textsecure.subscribeToPush = function(message_callback) {
if (decrypted.flags == null)
decrypted.flags = 0;
- if ((decrypted.flags & textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION)
- == textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION)
+ if ((decrypted.flags & textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
+ == textsecure.protobuf.PushMessageContent.Flags.END_SESSION)
return;
if (decrypted.flags != 0)
throw new Error("Unknown flags in message");
@@ -649,7 +606,7 @@ window.textsecure.subscribeToPush = function(message_callback) {
decrypted.group.id = getString(decrypted.group.id);
var existingGroup = textsecure.storage.groups.getNumbers(decrypted.group.id);
if (existingGroup === undefined) {
- if (decrypted.group.type != textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE)
+ if (decrypted.group.type != textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE)
throw new Error("Got message for unknown group");
textsecure.storage.groups.createNewGroup(decrypted.group.members, decrypted.group.id);
} else {
@@ -659,7 +616,7 @@ window.textsecure.subscribeToPush = function(message_callback) {
throw new Error("Sender was not a member of the group they were sending from");
switch(decrypted.group.type) {
- case textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE:
+ case textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE:
if (decrypted.group.avatar !== null)
promises.push(handleAttachment(decrypted.group.avatar));
@@ -682,12 +639,12 @@ window.textsecure.subscribeToPush = function(message_callback) {
decrypted.attachments = [];
break;
- case textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.QUIT:
+ case textsecure.protobuf.PushMessageContent.GroupContext.Type.QUIT:
textsecure.storage.groups.removeNumber(decrypted.group.id, proto.source);
decrypted.body = null;
decrypted.attachments = [];
- case textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.DELIVER:
+ case textsecure.protobuf.PushMessageContent.GroupContext.Type.DELIVER:
decrypted.group.name = null;
decrypted.group.members = [];
decrypted.group.avatar = null;
@@ -741,7 +698,7 @@ window.textsecure.registerSingleDevice = function(number, verificationCode, step
}
window.textsecure.registerSecondDevice = function(encodedDeviceInit, cryptoInfo, stepDone) {
- var deviceInit = textsecure.protos.decodeDeviceInit(encodedDeviceInit);
+ var deviceInit = textsecure.protobuf.DeviceInit.decode(encodedDeviceInit, 'binary');
return cryptoInfo.decryptAndHandleDeviceInit(deviceInit).then(function(identityKey) {
if (identityKey.server != textsecure.api.relay)
throw new Error("Unknown relay used by master");
diff --git a/js/protobufs.js b/js/protobufs.js
new file mode 100644
index 000000000..173e42089
--- /dev/null
+++ b/js/protobufs.js
@@ -0,0 +1,21 @@
+;(function() {
+
+ function loadProtoBufs(filename) {
+ return dcodeIO.ProtoBuf.loadProtoFile({root: 'protos', file: filename}).build('textsecure');
+ };
+
+ var pushMessages = loadProtoBufs('IncomingPushMessageSignal.proto');
+ var protocolMessages = loadProtoBufs('WhisperTextProtocol.proto');
+ var deviceMessages = loadProtoBufs('DeviceMessages.proto');
+
+ window.textsecure = window.textsecure || {};
+ window.textsecure.protobuf = {
+ IncomingPushMessageSignal : pushMessages.IncomingPushMessageSignal,
+ PushMessageContent : pushMessages.PushMessageContent,
+ WhisperMessage : protocolMessages.WhisperMessage,
+ PreKeyWhisperMessage : protocolMessages.PreKeyWhisperMessage,
+ DeviceInit : deviceMessages.DeviceInit,
+ IdentityKey : deviceMessages.IdentityKey,
+ DeviceControl : deviceMessages.DeviceControl
+ };
+})();
diff --git a/js/sendmessage.js b/js/sendmessage.js
index fb2354ff1..5a1b8c331 100644
--- a/js/sendmessage.js
+++ b/js/sendmessage.js
@@ -79,11 +79,11 @@ window.textsecure.messaging = function() {
for (var i in groups) {
var group = textsecure.storage.groups.getGroup(groups[i]);
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(group.id);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE;
proto.group.members = group.numbers;
proto.group.name = group.name === undefined ? null : group.name;
@@ -102,10 +102,10 @@ window.textsecure.messaging = function() {
var tryMessageAgain = function(number, encodedMessage, callback) {
//TODO: Wipe identity key!
refreshGroups(number).then(function() {
- var message = textsecure.protos.decodePushMessageContentProtobuf(encodedMessage);
+ var message = textsecure.protobuf.PushMessageContent.decode(encodedMessage, 'binary');
textsecure.sendMessage([number], message, callback);
});
- }
+ };
textsecure.replay.registerReplayFunction(tryMessageAgain, textsecure.replay.SEND_MESSAGE);
var sendMessageProto = function(numbers, message, callback) {
@@ -194,7 +194,7 @@ window.textsecure.messaging = function() {
}
makeAttachmentPointer = function(attachment) {
- var proto = new textsecure.protos.PushMessageContentProtobuf.AttachmentPointer();
+ var proto = new textsecure.protobuf.PushMessageContent.AttachmentPointer();
proto.key = textsecure.crypto.getRandomBytes(64);
var iv = textsecure.crypto.getRandomBytes(16);
@@ -233,7 +233,7 @@ window.textsecure.messaging = function() {
}
self.sendMessageToNumber = function(number, messageText, attachments) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
+ var proto = new textsecure.protobuf.PushMessageContent();
proto.body = messageText;
var promises = [];
@@ -246,9 +246,9 @@ window.textsecure.messaging = function() {
}
self.closeSession = function(number) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
+ var proto = new textsecure.protobuf.PushMessageContent();
proto.body = "TERMINATE";
- proto.flags = textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION;
+ proto.flags = textsecure.protobuf.PushMessageContent.Flags.END_SESSION;
return sendIndividualProto(number, proto).then(function(res) {
var devices = textsecure.storage.devices.getDeviceObjectsForNumber(number);
for (var i in devices)
@@ -259,11 +259,11 @@ window.textsecure.messaging = function() {
}
self.sendMessageToGroup = function(groupId, messageText, attachments) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
+ var proto = new textsecure.protobuf.PushMessageContent();
proto.body = messageText;
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(groupId);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.DELIVER;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.DELIVER;
var numbers = textsecure.storage.groups.getNumbers(groupId);
if (numbers === undefined)
@@ -279,14 +279,14 @@ window.textsecure.messaging = function() {
}
self.createGroup = function(numbers, name, avatar) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
var group = textsecure.storage.groups.createNewGroup(numbers);
proto.group.id = toArrayBuffer(group.id);
var numbers = group.numbers;
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE;
proto.group.members = numbers;
proto.group.name = name;
@@ -305,10 +305,10 @@ window.textsecure.messaging = function() {
}
self.addNumberToGroup = function(groupId, number) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(groupId);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE;
var numbers = textsecure.storage.groups.addNumbers(groupId, [number]);
if (numbers === undefined)
@@ -319,10 +319,10 @@ window.textsecure.messaging = function() {
}
self.setGroupName = function(groupId, name) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(groupId);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE;
proto.group.name = name;
var numbers = textsecure.storage.groups.getNumbers(groupId);
@@ -334,10 +334,10 @@ window.textsecure.messaging = function() {
}
self.setGroupAvatar = function(groupId, avatar) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(groupId);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.UPDATE;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.UPDATE;
var numbers = textsecure.storage.groups.getNumbers(groupId);
if (numbers === undefined)
@@ -351,10 +351,10 @@ window.textsecure.messaging = function() {
}
self.leaveGroup = function(groupId) {
- var proto = new textsecure.protos.PushMessageContentProtobuf();
- proto.group = new textsecure.protos.PushMessageContentProtobuf.GroupContext();
+ var proto = new textsecure.protobuf.PushMessageContent();
+ proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
proto.group.id = toArrayBuffer(groupId);
- proto.group.type = textsecure.protos.PushMessageContentProtobuf.GroupContext.Type.QUIT;
+ proto.group.type = textsecure.protobuf.PushMessageContent.GroupContext.Type.QUIT;
var numbers = textsecure.storage.groups.getNumbers(groupId);
if (numbers === undefined)
diff --git a/js/test.js b/js/test.js
index 4056f66ac..a38206371 100644
--- a/js/test.js
+++ b/js/test.js
@@ -291,15 +291,16 @@ describe("Axolotl", function() {
if (data.newEphemeralKey !== undefined)
privKeyQueue.push(data.newEphemeralKey);
- var message = new textsecure.protos.IncomingPushMessageProtobuf();
+ var message = new textsecure.protobuf.IncomingPushMessageSignal();
message.type = data.type;
message.source = "SNOWDEN";
message.message = data.message;
message.sourceDevice = 1;
try {
- return textsecure.crypto.handleIncomingPushMessageProto(textsecure.protos.decodeIncomingPushMessageProtobuf(getString(message.encode()))).then(function(res) {
+ var proto = textsecure.protobuf.IncomingPushMessageSignal.decode(message.encode());
+ return textsecure.crypto.handleIncomingPushMessageProto(proto).then(function(res) {
if (data.expectTerminateSession)
- return res.flags == textsecure.protos.PushMessageContentProtobuf.Flags.END_SESSION;
+ return res.flags == textsecure.protobuf.PushMessageContent.Flags.END_SESSION;
return res.body == data.expectedSmsText;
}).catch(function(e) {
if (data.expectException)
@@ -345,11 +346,11 @@ describe("Axolotl", function() {
//XXX: This should be all we do: isEqual(data.expectedCiphertext, msg.body, false);
if (msg.type == 1) {
var expected = getString(data.expectedCiphertext);
- var decoded = textsecure.protos.decodeWhisperMessageProtobuf(expected.substring(1, expected.length - 8));
+ var decoded = textsecure.protobuf.WhisperMessage.decode(expected.substring(1, expected.length - 8), 'binary');
var result = getString(msg.body);
return getString(decoded.encode()) == result.substring(1, result.length - 8);
} else {
- var decoded = textsecure.protos.decodePreKeyWhisperMessageProtobuf(getString(data.expectedCiphertext).substr(1));
+ var decoded = textsecure.protobuf.PreKeyWhisperMessage.decode(getString(data.expectedCiphertext).substr(1), 'binary');
var result = getString(msg.body).substring(1);
return getString(decoded.encode()) == result;
}
diff --git a/options.html b/options.html
index 98fb19fc9..961181285 100644
--- a/options.html
+++ b/options.html
@@ -104,6 +104,7 @@
+
diff --git a/test.html b/test.html
index 2a14722f0..bfe95511e 100644
--- a/test.html
+++ b/test.html
@@ -45,6 +45,7 @@
+