From 121671c99f2528014f64dae5c1b2e9215424b301 Mon Sep 17 00:00:00 2001 From: lilia Date: Tue, 21 Apr 2015 15:54:25 -0700 Subject: [PATCH] Store identity keys in indexeddb Let device storage request them from axolotl store rather than storing a copy. --- js/axolotl_store.js | 53 ++++++++++++++++++++++---------- js/libtextsecure.js | 28 +++++++++-------- libtextsecure/storage/devices.js | 28 +++++++++-------- 3 files changed, 68 insertions(+), 41 deletions(-) diff --git a/js/axolotl_store.js b/js/axolotl_store.js index 63d2c2e1f..ad2f05a65 100644 --- a/js/axolotl_store.js +++ b/js/axolotl_store.js @@ -55,6 +55,19 @@ return res; } + function equalArrayBuffers(ab1, ab2) { + if (ab1.bytelength !== ab2.bytelength) { + return false; + } + var result = true; + var ta1 = new Uint8Array(ab1); + var ta2 = new Uint8Array(ab2); + for (var i = 0; i < ab1.bytelength; ++i) { + if (ta1[i] !== ta2[i]) { result = false; } + } + return result; + } + var Model = Backbone.Model.extend({ database: Whisper.Database }); var PreKey = Model.extend({ storeName: 'preKeys' }); var SignedPreKey = Model.extend({ storeName: 'signedPreKeys' }); @@ -215,31 +228,37 @@ if (identifier === null || identifier === undefined) throw new Error("Tried to get identity key for undefined/null key"); var number = textsecure.utils.unencodeNumber(identifier)[0]; - return Promise.resolve(convertToArrayBuffer(function() { - var map = textsecure.storage.get("devices" + number); - return map === undefined ? undefined : map.identityKey; - }()); + return new Promise(function(resolve) { + var contact = new Contact({id: number}); + contact.fetch().always(function() { + resolve(contact.get('identityKey')); + }); + }); }, putIdentityKey: function(identifier, identityKey) { if (identifier === null || identifier === undefined) throw new Error("Tried to put identity key for undefined/null key"); var number = textsecure.utils.unencodeNumber(identifier)[0]; - return Promise.resolve((function() { - var map = textsecure.storage.get("devices" + number); - if (map === undefined) - textsecure.storage.put("devices" + number, { devices: [], identityKey: identityKey}); - else if (getString(map.identityKey) !== getString(identityKey)) - throw new Error("Attempted to overwrite a different identity key"); - })()); + return new Promise(function(resolve) { + var contact = new Contact({id: number}); + contact.fetch().always(function() { + var oldidentityKey = contact.get('identityKey'); + if (oldidentityKey && !equalArrayBuffers(oldidentityKey, identityKey)) + throw new Error("Attempted to overwrite a different identity key"); + contact.save({identityKey: identityKey}).then(resolve); + }); + }); }, removeIdentityKey: function(number) { - return Promise.resolve((function() { - var map = textsecure.storage.get("devices" + number); - if (map === undefined) + return new Promise(function(resolve) { + var contact = new Contact({id: number}); + contact.fetch().then(function() { + contact.save({identityKey: undefined}); + }).fail(function() { throw new Error("Tried to remove identity for unknown number"); - textsecure.storage.remove("devices" + number); - return textsecure.storage.axolotl.removeAllSessions(number); - })()); + }); + resolve(textsecure.storage.axolotl.removeAllSessions(number)); + }); }, diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 2f8c0932b..a5af29803 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -38118,12 +38118,15 @@ axolotlInternal.RecipientRecord = function() { }, getDeviceObjectsForNumber: function(number) { - return Promise.resolve((function() { + return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) { var map = textsecure.storage.get("devices" + number); if (map === undefined) return []; - return map.devices; - })()); + return map.devices.map(function(device) { + device.identityKey = identityKey; + return device; + }); + }); }, getDeviceObject: function(encodedNumber) { @@ -38171,17 +38174,18 @@ axolotlInternal.RecipientRecord = function() { }; var internalSaveDeviceObject = function(deviceObject, onlyKeys) { - return Promise.resolve((function() { - if (deviceObject.identityKey === undefined || deviceObject.encodedNumber === undefined) - throw new Error("Tried to store invalid deviceObject"); + if (deviceObject.encodedNumber === undefined) + throw new Error("Tried to store invalid deviceObject"); - var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0]; - var map = textsecure.storage.get("devices" + number); + var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0]; + var map = textsecure.storage.get("devices" + number); - if (map === undefined) - map = { devices: [deviceObject], identityKey: deviceObject.identityKey }; - else if (map.identityKey != getString(deviceObject.identityKey)) + return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) { + if (identityKey !== undefined && deviceObject.identityKey !== undefined && getString(identityKey) != getString(deviceObject.identityKey)) throw new Error("Identity key changed"); + + if (map === undefined) + map = { devices: [deviceObject] }; else { var updated = false; for (var i in map.devices) { @@ -38205,7 +38209,7 @@ axolotlInternal.RecipientRecord = function() { } textsecure.storage.put("devices" + number, map); - })()); + }); }; })(); diff --git a/libtextsecure/storage/devices.js b/libtextsecure/storage/devices.js index fd21b7f26..d594cf483 100644 --- a/libtextsecure/storage/devices.js +++ b/libtextsecure/storage/devices.js @@ -47,12 +47,15 @@ }, getDeviceObjectsForNumber: function(number) { - return Promise.resolve((function() { + return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) { var map = textsecure.storage.get("devices" + number); if (map === undefined) return []; - return map.devices; - })()); + return map.devices.map(function(device) { + device.identityKey = identityKey; + return device; + }); + }); }, getDeviceObject: function(encodedNumber) { @@ -100,17 +103,18 @@ }; var internalSaveDeviceObject = function(deviceObject, onlyKeys) { - return Promise.resolve((function() { - if (deviceObject.identityKey === undefined || deviceObject.encodedNumber === undefined) - throw new Error("Tried to store invalid deviceObject"); + if (deviceObject.encodedNumber === undefined) + throw new Error("Tried to store invalid deviceObject"); - var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0]; - var map = textsecure.storage.get("devices" + number); + var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0]; + var map = textsecure.storage.get("devices" + number); - if (map === undefined) - map = { devices: [deviceObject], identityKey: deviceObject.identityKey }; - else if (map.identityKey != getString(deviceObject.identityKey)) + return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) { + if (identityKey !== undefined && deviceObject.identityKey !== undefined && getString(identityKey) != getString(deviceObject.identityKey)) throw new Error("Identity key changed"); + + if (map === undefined) + map = { devices: [deviceObject] }; else { var updated = false; for (var i in map.devices) { @@ -134,6 +138,6 @@ } textsecure.storage.put("devices" + number, map); - })()); + }); }; })();