1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-26 17:03:12 +03:00

Make multi-room key restore work

This commit is contained in:
David Baker
2018-09-17 15:59:37 +01:00
parent e789747834
commit 073fb73ff3
2 changed files with 53 additions and 18 deletions

View File

@@ -68,6 +68,31 @@ try {
console.warn("Unable to load crypto module: crypto will be disabled: " + e); console.warn("Unable to load crypto module: crypto will be disabled: " + e);
} }
function keysFromRecoverySession(sessions, decryptionKey, roomId, keys) {
for (const [sessionId, sessionData] of Object.entries(sessions)) {
try {
const decrypted = keyFromRecoverySession(sessionData, decryptionKey, keys);
decrypted.session_id = sessionId;
decrypted.room_id = roomId;
return decrypted;
} catch (e) {
console.log("Failed to decrypt session from backup");
}
}
}
function keyFromRecoverySession(session, decryptionKey, keys) {
try {
keys.push(JSON.parse(decryptionKey.decrypt(
session.session_data.ephemeral,
session.session_data.mac,
session.session_data.ciphertext
)));
} catch (e) {
console.log("Failed to decrypt key from backup", e);
}
}
/** /**
* Construct a Matrix Client. Only directly construct this if you want to use * Construct a Matrix Client. Only directly construct this if you want to use
* custom modules. Normally, {@link createClient} should be used * custom modules. Normally, {@link createClient} should be used
@@ -966,7 +991,7 @@ MatrixClient.prototype.backupAllGroupSessions = function(version) {
return this._crypto.backupAllGroupSessions(version); return this._crypto.backupAllGroupSessions(version);
}; };
MatrixClient.prototype.restoreKeyBackups = function(decryptionKey, roomId, sessionId, version, callback) { MatrixClient.prototype.restoreKeyBackups = function(decryptionKey, targetRoomId, targetSessionId, version) {
if (this._crypto === null) { if (this._crypto === null) {
throw new Error("End-to-end encryption disabled"); throw new Error("End-to-end encryption disabled");
} }
@@ -975,28 +1000,36 @@ MatrixClient.prototype.restoreKeyBackups = function(decryptionKey, roomId, sessi
const decryption = new global.Olm.PkDecryption(); const decryption = new global.Olm.PkDecryption();
decryption.unpickle("secret_key", decryptionKey); decryption.unpickle("secret_key", decryptionKey);
const path = this._makeKeyBackupPath(roomId, sessionId, version); let totalKeyCount = 0;
const keys = [];
const path = this._makeKeyBackupPath(targetRoomId, targetSessionId, version);
return this._http.authedRequest( return this._http.authedRequest(
undefined, "GET", path.path, path.queryData, undefined, "GET", path.path, path.queryData,
).then((res) => { ).then((res) => {
const keys = []; if (res.rooms) {
// FIXME: for each room, session, if response has multiple for (const [roomId, roomData] of Object.entries(res.rooms)) {
// decrypt response.data.session_data if (!roomData.sessions) continue;
const session_data = res.session_data;
const key = JSON.parse(decryption.decrypt( totalKeyCount += Object.keys(roomData.sessions).length;
session_data.ephemeral, const roomKeys = [];
session_data.mac, keysFromRecoverySession(roomData.sessions, decryption, roomId, roomKeys);
session_data.ciphertext for (const k of roomKeys) {
)); k.room_id = roomId;
// set room_id and session_id keys.push(k);
key.room_id = roomId; }
key.session_id = sessionId; }
keys.push(key); } else if (res.sessions) {
totalKeyCount = Object.keys(res.sessions).length;
keys.push(...keysFromRecoverySession(res.sessions, decryption, roomId, keys));
} else {
totalKeyCount = 1;
keys.push(keyFromRecoverySession(res, decryption, keys));
}
return this.importRoomKeys(keys); return this.importRoomKeys(keys);
}).then(() => { }).then(() => {
if (callback) { return {total: totalKeyCount, imported: keys.length};
callback();
}
}) })
}; };

View File

@@ -851,6 +851,8 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
if (this._crypto.backupInfo) { if (this._crypto.backupInfo) {
// XXX: No retries on this at all: if this request dies for whatever // XXX: No retries on this at all: if this request dies for whatever
// reason, this key will never be uploaded. // reason, this key will never be uploaded.
// More XXX: If this fails it'll cause the message send to fail,
// and this will happen if the backup is deleted from another client.
return this._crypto.backupGroupSession( return this._crypto.backupGroupSession(
content.room_id, senderKey, forwardingKeyChain, content.room_id, senderKey, forwardingKeyChain,
content.session_id, content.session_key, keysClaimed, content.session_id, content.session_key, keysClaimed,