You've already forked matrix-js-sdk
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:
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
11
src/crypto/store/base.js
Normal 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
|
||||||
|
*/
|
||||||
98
src/crypto/store/indexeddb-crypto-store.js
Normal file
98
src/crypto/store/indexeddb-crypto-store.js
Normal 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");
|
||||||
|
}
|
||||||
29
src/crypto/store/memory-crypto-store.js
Normal file
29
src/crypto/store/memory-crypto-store.js
Normal 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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user