1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-28 05:03:59 +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");
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
global.matrixcs = matrixcs;

View File

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

View File

@@ -1,5 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
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.
@@ -15,7 +16,6 @@ limitations under the License.
*/
"use strict";
/**
* @module crypto
*/
@@ -50,14 +50,18 @@ const DeviceList = require('./DeviceList').default;
* @param {string} deviceId The identifier for this device.
*
* @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,
clientStore) {
clientStore, cryptoStore) {
this._baseApis = baseApis;
this._sessionStore = sessionStore;
this._userId = userId;
this._deviceId = deviceId;
this._clientStore = clientStore;
this._cryptoStore = cryptoStore;
this._olmDevice = new OlmDevice(sessionStore);
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.MemoryCryptoStore =
require("./crypto/store/memory-crypto-store").default;
module.exports.IndexedDBCryptoStore =
require("./crypto/store/indexeddb-crypto-store").default;
/**
* Create a new Matrix Call.
* @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}
* except that the 'request', 'store' and 'scheduler' dependencies are satisfied.
@@ -136,6 +154,11 @@ module.exports.wrapRequest = function(wrapper) {
* {@link module:scheduler~MatrixScheduler}.
* @param {requestFunction} opts.request If not set, defaults to the function
* 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.
* @see {@link module:client~MatrixClient} for the full list of options for
* <code>opts</code>.
@@ -151,6 +174,7 @@ module.exports.createClient = function(opts) {
localStorage: global.localStorage,
});
opts.scheduler = opts.scheduler || new module.exports.MatrixScheduler();
opts.cryptoStore = opts.cryptoStore || cryptoStoreFactory();
return new module.exports.MatrixClient(opts);
};