1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Support for exporting megolm session data

This commit is contained in:
Richard van der Hoff
2017-01-14 00:12:21 +00:00
parent 0fa9f7c609
commit 766d8f0ba4
5 changed files with 108 additions and 1 deletions

View File

@@ -193,6 +193,12 @@ module.exports.MockStorageApi = function() {
this.data = {};
};
module.exports.MockStorageApi.prototype = {
get length() {
return Object.keys(this.data).length;
},
key: function(i) {
return Object.keys(this.data)[i];
},
setItem: function(k, v) {
this.data[k] = v;
},

View File

@@ -461,6 +461,21 @@ MatrixClient.prototype.isRoomEncrypted = function(roomId) {
return this._crypto.isRoomEncrypted(roomId);
};
/**
* Get a list containing all of the room keys
*
* This should be encrypted before returning it to the user.
*
* @return {module:client.Promise} a promise which resolves to a list of
* session export objects
*/
MatrixClient.prototype.exportRoomKeys = function() {
if (!this._crypto) {
return q.reject(new Error("End-to-end encryption disabled"));
}
return this._crypto.exportRoomKeys();
};
/**
* Decrypt a received event according to the algorithm specified in the event.
*

View File

@@ -739,6 +739,41 @@ OlmDevice.prototype.decryptGroupMessage = function(
);
};
/**
* Export an inbound group session
*
* @param {string} senderKey base64-encoded curve25519 key of the sender
* @param {string} sessionId session identifier
* @return {object} exported session data
*/
OlmDevice.prototype.exportInboundGroupSession = function(senderKey, sessionId) {
const s = this._sessionStore.getEndToEndInboundGroupSession(
senderKey, sessionId
);
if (s === null) {
throw new Error("Unknown inbound group session [" + senderKey + "," +
sessionId + "]");
}
const r = JSON.parse(s);
const session = new Olm.InboundGroupSession();
try {
session.unpickle(this._pickleKey, r.session);
const messageIndex = session.first_known_index();
return {
"sender_key": senderKey,
"sender_claimed_keys": r.keysClaimed,
"room_id": r.room_id,
"session_id": sessionId,
"session_key": session.export_session(messageIndex),
};
} finally {
session.free();
}
};
// Utilities
// =========

View File

@@ -897,6 +897,28 @@ Crypto.prototype.isRoomEncrypted = function(roomId) {
return Boolean(this._roomEncryptors[roomId]);
};
/**
* Get a list containing all of the room keys
*
* @return {module:client.Promise} a promise which resolves to a list of
* session export objects
*/
Crypto.prototype.exportRoomKeys = function() {
return q(
this._sessionStore.getAllEndToEndInboundGroupSessionKeys().map(
(s) => {
const sess = this._olmDevice.exportInboundGroupSession(
s.senderKey, s.sessionId
);
sess.algorithm = olmlib.MEGOLM_ALGORITHM;
return sess;
}
)
);
};
/**
* Encrypt an event according to the configuration of the room, if necessary.
*

View File

@@ -37,7 +37,10 @@ function WebStorageSessionStore(webStore) {
this.store = webStore;
if (!utils.isFunction(webStore.getItem) ||
!utils.isFunction(webStore.setItem) ||
!utils.isFunction(webStore.removeItem)) {
!utils.isFunction(webStore.removeItem) ||
!utils.isFunction(webStore.key) ||
typeof(webStore.length) !== 'number'
) {
throw new Error(
"Supplied webStore does not meet the WebStorage API interface"
);
@@ -120,6 +123,32 @@ WebStorageSessionStore.prototype = {
return getJsonItem(this.store, keyEndToEndSessions(deviceKey));
},
/**
* Retrieve a list of all known inbound group sessions
*
* @return {{senderKey: string, sessionId: string}}
*/
getAllEndToEndInboundGroupSessionKeys: function() {
const prefix = E2E_PREFIX + 'inboundgroupsessions/';
const result = [];
for (let i = 0; i < this.store.length; i++) {
const key = this.store.key(i);
if (!key.startsWith(prefix)) {
continue;
}
// we can't use split, as the components we are trying to split out
// might themselves contain '/' characters. We rely on the
// senderKey being a (32-byte) curve25519 key, base64-encoded
// (hence 43 characters long).
result.push({
senderKey: key.substr(prefix.length, 43),
sessionId: key.substr(prefix.length + 44),
});
}
return result;
},
getEndToEndInboundGroupSession: function(senderKey, sessionId) {
let key = keyEndToEndInboundGroupSession(senderKey, sessionId);
return this.store.getItem(key);