1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-29 16:43:09 +03:00

Initial framework for indexeddb-backed crypto store

Doesn't do anything useful yet - just demonstrates a framework for how I hope
it will fit into the sdk.
This commit is contained in:
Richard van der Hoff
2017-05-30 23:25:07 +01:00
parent 676515cf27
commit 4c7afe5af0
7 changed files with 178 additions and 2 deletions

View File

@@ -1,4 +1,13 @@
var matrixcs = require("./lib/matrix"); var matrixcs = require("./lib/matrix");
matrixcs.request(require("browser-request")); matrixcs.request(require("browser-request"));
matrixcs.setCryptoStoreFactory(
function() {
return new matrixcs.IndexedDBCryptoStore(
global.indexedDB, "matrix-js-sdk:crypto"
);
}
);
module.exports = matrixcs; // keep export for browserify package deps module.exports = matrixcs; // keep export for browserify package deps
global.matrixcs = matrixcs; global.matrixcs = matrixcs;

View File

@@ -160,6 +160,7 @@ function MatrixClient(opts) {
opts.sessionStore, opts.sessionStore,
userId, this.deviceId, userId, this.deviceId,
this.store, this.store,
opts.cryptoStore,
); );
this.olmVersion = Crypto.getOlmVersion(); this.olmVersion = Crypto.getOlmVersion();

View File

@@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -15,7 +16,6 @@ limitations under the License.
*/ */
"use strict"; "use strict";
/** /**
* @module crypto * @module crypto
*/ */
@@ -50,14 +50,18 @@ const DeviceList = require('./DeviceList').default;
* @param {string} deviceId The identifier for this device. * @param {string} deviceId The identifier for this device.
* *
* @param {Object} clientStore the MatrixClient data store. * @param {Object} clientStore the MatrixClient data store.
*
* @param {module:crypto/store/base~CryptoStore} cryptoStore
* storage for the crypto layer.
*/ */
function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId, function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId,
clientStore) { clientStore, cryptoStore) {
this._baseApis = baseApis; this._baseApis = baseApis;
this._sessionStore = sessionStore; this._sessionStore = sessionStore;
this._userId = userId; this._userId = userId;
this._deviceId = deviceId; this._deviceId = deviceId;
this._clientStore = clientStore; this._clientStore = clientStore;
this._cryptoStore = cryptoStore;
this._olmDevice = new OlmDevice(sessionStore); this._olmDevice = new OlmDevice(sessionStore);
this._deviceList = new DeviceList(baseApis, sessionStore, this._olmDevice); this._deviceList = new DeviceList(baseApis, sessionStore, this._olmDevice);

11
src/crypto/store/base.js Normal file
View File

@@ -0,0 +1,11 @@
/**
* Internal module. Defintions for storage for the crypto module
*
* @module
*/
/**
* Abstraction of things that can store data required for end-to-end encryption
*
* @interface CryptoStore
*/

View File

@@ -0,0 +1,98 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import q from 'q';
/**
* Internal module. indexeddb storage for e2e.
*
* @module
*/
const VERSION = 1;
/**
* @implements {module:crypto/store/base~CryptoStore}
*/
export default class IndexedDBCryptoStore {
constructor(indexedDB, dbName) {
if (!indexedDB) {
throw new Error("must pass indexedDB into IndexedDBCryptoStore");
}
this._indexedDB = indexedDB;
this._dbName = dbName;
this._dbPromise = null;
}
/**
* Ensure the database exists and is up-to-date
*
* @return {Promise} resolves to an instance of IDBDatabase when
* the database is ready
*/
connect() {
if (this._dbPromise) {
return this._dbPromise;
}
this._dbPromise = new q.Promise((resolve, reject) => {
const req = this._indexedDB.open(this._dbName, VERSION);
req.onupgradeneeded = (ev) => {
const db = ev.target.result;
const oldVersion = ev.oldVersion;
console.log(
`Upgrading IndexedDBCryptoStore from version ${oldVersion}`
+ ` to ${VERSION}`,
);
if (oldVersion < 1) { // The database did not previously exist.
createDatabase(db);
}
// Expand as needed.
};
req.onblocked = () => {
reject(new Error(
"unable to upgrade indexeddb because it is open elsewhere",
));
};
req.onerror = (ev) => {
reject(new Error(
"unable to connect to indexeddb: " + ev.target.error,
));
};
req.onsuccess = (r) => {
resolve(r.target.result);
};
});
return this._dbPromise;
}
}
function createDatabase(db) {
const outgoingRoomKeyRequestsStore =
db.createObjectStore("outgoingRoomKeyRequests", { keyPath: "requestId" });
// we assume that the RoomKeyRequestBody will have room_id and session_id
// properties, to make the index efficient.
outgoingRoomKeyRequestsStore.createIndex("session",
["requestBody.room_id", "requestBody.session_id"],
);
outgoingRoomKeyRequestsStore.createIndex("state", "state");
}

View File

@@ -0,0 +1,29 @@
/*
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* Internal module. in-memory storage for e2e.
*
* @module
*/
/**
* @implements {module:crypto/store/base~CryptoStore}
*/
export default class MemoryCryptoStore {
constructor() {
}
}

View File

@@ -63,6 +63,11 @@ module.exports.TimelineWindow = require("./timeline-window").TimelineWindow;
module.exports.InteractiveAuth = require("./interactive-auth"); module.exports.InteractiveAuth = require("./interactive-auth");
module.exports.MemoryCryptoStore =
require("./crypto/store/memory-crypto-store").default;
module.exports.IndexedDBCryptoStore =
require("./crypto/store/indexeddb-crypto-store").default;
/** /**
* Create a new Matrix Call. * Create a new Matrix Call.
* @function * @function
@@ -124,6 +129,19 @@ module.exports.wrapRequest = function(wrapper) {
}; };
}; };
let cryptoStoreFactory = () => new module.exports.MemoryCryptoStore;
/**
* Configure a different factory to be used for creating crypto stores
*
* @param {Function} fac a funciton which will return a new
* {@link module:crypto.store.base~CryptoStore}.
*/
module.exports.setCryptoStoreFactory = function(fac) {
cryptoStoreFactory = fac;
};
/** /**
* Construct a Matrix Client. Similar to {@link module:client~MatrixClient} * Construct a Matrix Client. Similar to {@link module:client~MatrixClient}
* except that the 'request', 'store' and 'scheduler' dependencies are satisfied. * except that the 'request', 'store' and 'scheduler' dependencies are satisfied.
@@ -136,6 +154,11 @@ module.exports.wrapRequest = function(wrapper) {
* {@link module:scheduler~MatrixScheduler}. * {@link module:scheduler~MatrixScheduler}.
* @param {requestFunction} opts.request If not set, defaults to the function * @param {requestFunction} opts.request If not set, defaults to the function
* supplied to {@link request} which defaults to the request module from NPM. * supplied to {@link request} which defaults to the request module from NPM.
*
* @param {module:crypto.store.base~CryptoStore=} opts.cryptoStore
* crypto store implementation. Calls the factory supplied to
* {@link setCryptoStoreFactory if unspecified}
*
* @return {MatrixClient} A new matrix client. * @return {MatrixClient} A new matrix client.
* @see {@link module:client~MatrixClient} for the full list of options for * @see {@link module:client~MatrixClient} for the full list of options for
* <code>opts</code>. * <code>opts</code>.
@@ -151,6 +174,7 @@ module.exports.createClient = function(opts) {
localStorage: global.localStorage, localStorage: global.localStorage,
}); });
opts.scheduler = opts.scheduler || new module.exports.MatrixScheduler(); opts.scheduler = opts.scheduler || new module.exports.MatrixScheduler();
opts.cryptoStore = opts.cryptoStore || cryptoStoreFactory();
return new module.exports.MatrixClient(opts); return new module.exports.MatrixClient(opts);
}; };