From 77602e3dbb101bd97f655a7d86afdd71b7a87c24 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Thu, 8 Nov 2018 08:52:03 +1100 Subject: [PATCH] Moved contactPreKey and contactSignedPreKey to sql. --- app/sql.js | 141 ++++++++++++++++++++ js/modules/data.js | 82 ++++++++++++ js/signal_protocol_store.js | 205 +++++++++++------------------- libloki/libloki-protocol.js | 2 +- libtextsecure/outgoing_message.js | 8 +- 5 files changed, 301 insertions(+), 137 deletions(-) diff --git a/app/sql.js b/app/sql.js index 7c56fec09..e1aa11636 100644 --- a/app/sql.js +++ b/app/sql.js @@ -43,6 +43,22 @@ module.exports = { removeSignedPreKeyById, removeAllSignedPreKeys, + createOrUpdateContactPreKey, + getContactPreKeyById, + getContactPreKeyByIdentityKey, + getContactPreKeys, + bulkAddContactPreKeys, + removeContactPreKeyById, + removeAllContactPreKeys, + + createOrUpdateContactSignedPreKey, + getContactSignedPreKeyById, + getContactSignedPreKeyByIdentityKey, + getContactSignedPreKeys, + bulkAddContactSignedPreKeys, + removeContactSignedPreKeyById, + removeAllContactSignedPreKeys, + createOrUpdateItem, getItemById, getAllItems, @@ -419,6 +435,24 @@ async function updateToSchemaVersion6(currentVersion, instance) { );` ); + await instance.run( + `CREATE TABLE contactPreKeys( + id INTEGER PRIMARY KEY ASC AUTO_INCREMENT, + keyId INTEGER, + identityKeyString STRING, + json TEXT + );` + ); + + await instance.run( + `CREATE TABLE contactSignedPreKeys( + id INTEGER PRIMARY KEY ASC AUTO_INCREMENT, + identityKeyString STRING, + keyId INTEGER, + json TEXT + );` + ); + await instance.run('PRAGMA schema_version = 6;'); await instance.run('COMMIT TRANSACTION;'); console.log('updateToSchemaVersion6: success!'); @@ -607,6 +641,113 @@ async function removeAllPreKeys() { return removeAllFromTable(PRE_KEYS_TABLE); } +const CONTACT_PRE_KEYS_TABLE = 'contactPreKeys'; +async function createOrUpdateContactPreKey(data) { + const { keyId, identityKeyString } = data; + + await db.run( + `INSERT OR REPLACE INTO ${CONTACT_PRE_KEYS_TABLE} ( + keyId, + identityKeyString, + json + ) values ( + $keyId, + $identityKeyString, + $json + )`, + { + $keyId: keyId, + $identityKeyString: identityKeyString || '', + $json: objectToJSON(data), + } + ); +} +async function getContactPreKeyById(id) { + return getById(CONTACT_PRE_KEYS_TABLE, id); +} +async function getContactPreKeyByIdentityKey(key) { + const row = await db.get(`SELECT * FROM ${CONTACT_PRE_KEYS_TABLE} WHERE identityKeyString = $identityKeyString;`, { + $identityKeyString: key, + }); + + if (!row) { + return null; + } + + return jsonToObject(row.json); +} +async function getContactPreKeys(keyId, identityKeyString) { + const query = `SELECT * FROM ${CONTACT_PRE_KEYS_TABLE} WHERE identityKeyString = $identityKeyString AND keyId = $keyId;`; + const rows = await db.all(query, { + $keyId: keyId, + $identityKeyString: identityKeyString, + }); + return map(rows, row => jsonToObject(row.json)); +} + +async function bulkAddContactPreKeys(array) { + return bulkAdd(CONTACT_PRE_KEYS_TABLE, array); +} +async function removeContactPreKeyById(id) { + return removeById(CONTACT_PRE_KEYS_TABLE, id); +} +async function removeAllContactPreKeys() { + return removeAllFromTable(CONTACT_PRE_KEYS_TABLE); +} + +const CONTACT_SIGNED_PRE_KEYS_TABLE = 'contactSignedPreKeys'; +async function createOrUpdateContactSignedPreKey(data) { + const { keyId, identityKeyString } = data; + + await db.run( + `INSERT OR REPLACE INTO ${CONTACT_SIGNED_PRE_KEYS_TABLE} ( + keyId, + identityKeyString, + json + ) values ( + $keyId, + $identityKeyString, + $json + )`, + { + $keyId: keyId, + $identityKeyString: identityKeyString || '', + $json: objectToJSON(data), + } + ); +} +async function getContactSignedPreKeyById(id) { + return getById(CONTACT_SIGNED_PRE_KEYS_TABLE, id); +} +async function getContactSignedPreKeyByIdentityKey(key) { + const row = await db.get(`SELECT * FROM ${CONTACT_SIGNED_PRE_KEYS_TABLE} WHERE identityKeyString = $identityKeyString;`, { + $identityKeyString: key, + }); + + if (!row) { + return null; + } + + return jsonToObject(row.json); +} +async function getContactSignedPreKeys(keyId, identityKeyString) { + const query = `SELECT * FROM ${CONTACT_SIGNED_PRE_KEYS_TABLE} WHERE identityKeyString = $identityKeyString AND keyId = $keyId;`; + const rows = await db.all(query, { + $keyId: keyId, + $identityKeyString: identityKeyString, + }); + return map(rows, row => jsonToObject(row.json)); +} +async function bulkAddContactSignedPreKeys(array) { + return bulkAdd(CONTACT_SIGNED_PRE_KEYS_TABLE, array); +} +async function removeContactSignedPreKeyById(id) { + return removeById(CONTACT_SIGNED_PRE_KEYS_TABLE, id); +} +async function removeAllContactSignedPreKeys() { + return removeAllFromTable(CONTACT_SIGNED_PRE_KEYS_TABLE); +} + const SIGNED_PRE_KEYS_TABLE = 'signedPreKeys'; async function createOrUpdateSignedPreKey(data) { return createOrUpdate(SIGNED_PRE_KEYS_TABLE, data); diff --git a/js/modules/data.js b/js/modules/data.js index ae886c206..eaf1e8a7b 100644 --- a/js/modules/data.js +++ b/js/modules/data.js @@ -69,6 +69,23 @@ module.exports = { removeSignedPreKeyById, removeAllSignedPreKeys, + createOrUpdateContactPreKey, + getContactPreKeyById, + getContactPreKeyByIdentityKey, + getContactPreKeys, + getAllContactPreKeys, + bulkAddContactPreKeys, + removeContactPreKeyById, + removeAllContactPreKeys, + + createOrUpdateContactSignedPreKey, + getContactSignedPreKeyById, + getContactSignedPreKeyByIdentityKey, + getContactSignedPreKeys, + bulkAddContactSignedPreKeys, + removeContactSignedPreKeyById, + removeAllContactSignedPreKeys, + createOrUpdateItem, getItemById, getAllItems, @@ -381,6 +398,10 @@ async function getPreKeyById(id) { const data = await channels.getPreKeyById(id); return keysToArrayBuffer(PRE_KEY_KEYS, data); } +async function getPreKeyByRecipent(recipient) { + const data = await channels.getPreKeyByRecipent(recipient); + return keysToArrayBuffer(PRE_KEY_KEYS, data); +} async function bulkAddPreKeys(array) { const updated = map(array, data => keysFromArrayBuffer(PRE_KEY_KEYS, data)); await channels.bulkAddPreKeys(updated); @@ -418,6 +439,67 @@ async function removeAllSignedPreKeys() { await channels.removeAllSignedPreKeys(); } +// Contact Pre Key +async function createOrUpdateContactPreKey(data) { + const updated = keysFromArrayBuffer(PRE_KEY_KEYS, data); + await channels.createOrUpdateContactPreKey(updated); +} +async function getContactPreKeyById(id) { + const data = await channels.getContactPreKeyById(id); + return keysToArrayBuffer(PRE_KEY_KEYS, data); +} +async function getContactPreKeyByIdentityKey(key) { + const data = await channels.getContactPreKeyByIdentityKey(key); + return keysToArrayBuffer(PRE_KEY_KEYS, data); +} +async function getContactPreKeys(keyId, identityKeyString) { + const keys = await channels.getContactPreKeys(keyId, identityKeyString); + return keys.map(k => keysToArrayBuffer(PRE_KEY_KEYS, data)); +} +async function getAllContactPreKeys() { + const keys = await channels.getAllContactPreKeys(); + return keys; +} +async function bulkAddContactPreKeys(array) { + const updated = map(array, data => keysFromArrayBuffer(PRE_KEY_KEYS, data)); + await channels.bulkAddContactPreKeys(updated); +} +async function removeContactPreKeyById(id) { + await channels.removePreContactKeyById(id); +} +async function removeAllContactPreKeys() { + await channels.removeAllContactPreKeys(); +} + +// Contact Signed Pre Key +async function createOrUpdateContactSignedPreKey(data) { + const updated = keysFromArrayBuffer(PRE_KEY_KEYS, data); + await channels.createOrUpdateContactSignedPreKey(updated); +} +async function getContactSignedPreKeyById(id) { + const data = await channels.getContactSignedPreKeyById(id); + return keysToArrayBuffer(PRE_KEY_KEYS, data); +} +async function getContactSignedPreKeyByIdentityKey(key) { + const data = await channels.getContactSignedPreKeyByIdentityKey(key); + return keysToArrayBuffer(PRE_KEY_KEYS, data); +} +async function getContactSignedPreKeys(keyId, identityKeyString) { + const keys = await channels.getContactSignedPreKeys(keyId, identityKeyString); + return keys.map(k => keysToArrayBuffer(PRE_KEY_KEYS, data)); +} +async function bulkAddContactSignedPreKeys(array) { + const updated = map(array, data => keysFromArrayBuffer(PRE_KEY_KEYS, data)); + await channels.bulkAddContactSignedPreKeys(updated); +} +async function removeContactSignedPreKeyById(id) { + await channels.removePreContactSignedKeyById(id); +} +async function removeAllContactSignedPreKeys() { + await channels.removeAllContactSignedPreKeys(); +} + + // Items const ITEM_KEYS = { diff --git a/js/signal_protocol_store.js b/js/signal_protocol_store.js index 518ca0392..450dca7cb 100644 --- a/js/signal_protocol_store.js +++ b/js/signal_protocol_store.js @@ -148,28 +148,6 @@ }, }); - const Model = Backbone.Model.extend({ database: Whisper.Database }); - const ContactPreKey = Model.extend({ storeName: 'contactPreKeys' }); - const ContactPreKeyCollection = Backbone.Collection.extend({ - storeName: 'contactPreKeys', - database: Whisper.Database, - model: ContactPreKey, - fetchBy(filter) { - return this.fetch({ conditions: filter }); - }, - }); - const ContactSignedPreKey = Model.extend({ - storeName: 'contactSignedPreKeys', - }); - const ContactSignedPreKeyCollection = Backbone.Collection.extend({ - storeName: 'contactSignedPreKeys', - database: Whisper.Database, - model: ContactSignedPreKey, - fetchBy(filter) { - return this.fetch({ conditions: filter }); - }, - }); - function SignalProtocolStore() {} SignalProtocolStore.prototype = { @@ -220,62 +198,47 @@ }; } }, - loadContactPreKey(pubKey) { - const prekey = new ContactPreKey({ identityKeyString: pubKey }); - return new Promise(resolve => { - prekey.fetch().then( - () => { - window.log.info('Successfully fetched contact prekey:', pubKey); - resolve({ - id: prekey.get('id'), - keyId: prekey.get('keyId'), - publicKey: prekey.get('publicKey'), - identityKeyString: prekey.get('identityKeyString'), - }); - }, - () => { - window.log.error('Failed to fetch contact prekey:', pubKey); - resolve(); - } - ); - }); + async loadContactPreKey(pubKey) { + const preKey = await window.Signal.Data.getContactPreKeyByIdentityKey(pubKey); + if (preKey) { + return { + id: preKey.id, + keyId: preKey.keyId, + publicKey: preKey.publicKey, + identityKeyString: preKey.identityKeyString, + } + } + + window.log.error('Failed to fetch contact prekey:', pubKey); + return undefined; }, - loadContactPreKeys(filters) { - const contactPreKeys = new ContactPreKeyCollection(); - return new Promise((resolve, reject) => { - contactPreKeys - .fetchBy(filters) - .then(() => { - resolve( - contactPreKeys.map(prekey => ({ - id: prekey.get('id'), - keyId: prekey.get('keyId'), - publicKey: prekey.get('publicKey'), - identityKeyString: prekey.get('identityKeyString'), - })) - ); - }) - .fail(e => { - window.log.error( - 'Failed to fetch signed prekey with filters', - filters - ); - reject(e); - }); - }); + async loadContactPreKeys(filters) { + const { keyId, identityKeyString } = filters; + const keys = await window.Signal.Data.getContactPreKeys(keyId, identityKeyString); + if (keys) { + return keys.map(preKey => ({ + id: preKey.id, + keyId: preKey.keyId, + publicKey: preKey.publicKey, + identityKeyString: preKey.identityKeyString, + })); + } + + window.log.error( + 'Failed to fetch signed prekey with filters', + filters + ); + return undefined; }, - storeContactPreKey(pubKey, preKey) { - const prekey = new ContactPreKey({ + async storeContactPreKey(pubKey, preKey) { + const key = { // id: (autoincrement) identityKeyString: pubKey, publicKey: preKey.publicKey, keyId: preKey.keyId, - }); - return new Promise(resolve => { - prekey.save().always(() => { - resolve(); - }); - }); + }; + + await window.Signal.Data.createorUpdateContactPreKey(key); }, async storePreKey(keyId, keyPair, contactIdentityKeyString) { const data = { @@ -321,58 +284,42 @@ window.log.error('Failed to fetch signed prekey:', keyId); return undefined; }, - loadContactSignedPreKeys(filters) { - const contactSignedPreKeys = new ContactSignedPreKeyCollection(); - return new Promise((resolve, reject) => { - contactSignedPreKeys - .fetchBy(filters) - .then(() => { - resolve( - contactSignedPreKeys.map(prekey => ({ - id: prekey.get('id'), - identityKeyString: prekey.get('identityKeyString'), - publicKey: prekey.get('publicKey'), - signature: prekey.get('signature'), - created_at: prekey.get('created_at'), - keyId: prekey.get('keyId'), - confirmed: prekey.get('confirmed'), - })) - ); - }) - .fail(e => { - window.log.error( - 'Failed to fetch signed prekey with filters', - filters - ); - reject(e); - }); - }); + async loadContactSignedPreKeys(filters) { + const { keyId, identityKeyString } = filters; + const keys = await window.Signal.Data.getContactSignedPreKeys(keyId, identityKeyString); + if (keys) { + return keys.map(preKey => ({ + id: preKey.id, + identityKeyString: preKey.identityKeyString, + publicKey: preKey.publicKey, + signature: preKey.signature, + created_at: preKey.created_at, + keyId: preKey.keyId, + confirmed: preKey.confirmed, + })); + } + + window.log.error( + 'Failed to fetch contact signed prekey with filters', + filters + ); + return undefined; }, - loadContactSignedPreKey(pubKey) { - const prekey = new ContactSignedPreKey({ identityKeyString: pubKey }); - return new Promise(resolve => { - prekey - .fetch() - .then(() => { - window.log.info( - 'Successfully fetched signed prekey:', - prekey.get('id') - ); - resolve({ - id: prekey.get('id'), - identityKeyString: prekey.get('identityKeyString'), - publicKey: prekey.get('publicKey'), - signature: prekey.get('signature'), - created_at: prekey.get('created_at'), - keyId: prekey.get('keyId'), - confirmed: prekey.get('confirmed'), - }); - }) - .fail(() => { - window.log.error('Failed to fetch signed prekey:', pubKey); - resolve(); - }); - }); + async loadContactSignedPreKey(pubKey) { + const preKey = await window.Signal.Data.getContactSignedPreKeyByIdentityKey(pubKey); + if (preKey) { + return { + id: preKey.id, + identityKeyString: preKey.identityKeyString, + publicKey: preKey.publicKey, + signature: preKey.signature, + created_at: preKey.created_at, + keyId: preKey.keyId, + confirmed: preKey.confirmed, + }; + } + window.log.error('Failed to fetch contact signed prekey:', pubKey); + return undefined; }, async loadSignedPreKeys() { if (arguments.length > 0) { @@ -400,8 +347,8 @@ }; await window.Signal.Data.createOrUpdateSignedPreKey(key); }, - storeContactSignedPreKey(pubKey, signedPreKey) { - const prekey = new ContactSignedPreKey({ + async storeContactSignedPreKey(pubKey, signedPreKey) { + const key = { // id: (autoincrement) identityKeyString: pubKey, keyId: signedPreKey.keyId, @@ -409,12 +356,8 @@ signature: signedPreKey.signature, created_at: Date.now(), confirmed: false, - }); - return new Promise(resolve => { - prekey.save().always(() => { - resolve(); - }); - }); + }; + await window.Signal.Date.createorUpdateContactSignedPreKey(key); }, async removeSignedPreKey(keyId) { await window.Signal.Data.removeSignedPreKeyById(keyId); diff --git a/libloki/libloki-protocol.js b/libloki/libloki-protocol.js index 4e63ed01b..4409c286c 100644 --- a/libloki/libloki-protocol.js +++ b/libloki/libloki-protocol.js @@ -132,7 +132,7 @@ }); const preKeyPromise = new Promise(async resolve => { - const existingPreKeys = textsecure.storage.protocol.loadContactPreKeys({ + const existingPreKeys = await textsecure.storage.protocol.loadContactPreKeys({ identityKeyString: pubKey, keyId: preKeyId, }); diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 8159cc0aa..ec4050b0f 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -1,4 +1,3 @@ -<<<<<<< HEAD /* global textsecure, libsignal, @@ -8,10 +7,9 @@ StringView, dcodeIO, log, - */ -======= -/* global textsecure, libsignal, window, btoa, _ */ ->>>>>>> sig-development + btoa, + _ +*/ /* eslint-disable more/no-then */