add method to fetch missing sender keys

This commit is contained in:
Bruno Windels 2022-10-28 15:41:18 +02:00
parent c544819b42
commit 9c13b2b4a4
3 changed files with 34 additions and 3 deletions

View File

@ -27,6 +27,7 @@ limitations under the License.
*/ */
import type {DeviceIdentity} from "../storage/idb/stores/DeviceIdentityStore"; import type {DeviceIdentity} from "../storage/idb/stores/DeviceIdentityStore";
import type {TimelineEvent} from "../storage/types";
type DecryptedEvent = { type DecryptedEvent = {
type?: string, type?: string,
@ -35,12 +36,12 @@ type DecryptedEvent = {
export class DecryptionResult { export class DecryptionResult {
private device?: DeviceIdentity; private device?: DeviceIdentity;
private roomTracked: boolean = true;
constructor( constructor(
public readonly event: DecryptedEvent, public readonly event: DecryptedEvent,
public readonly senderCurve25519Key: string, public readonly senderCurve25519Key: string,
public readonly claimedEd25519Key: string public readonly claimedEd25519Key: string,
public readonly encryptedEvent?: TimelineEvent
) {} ) {}
setDevice(device: DeviceIdentity): void { setDevice(device: DeviceIdentity): void {

View File

@ -221,7 +221,30 @@ export class RoomEncryption {
})); }));
} }
/** fetches the devices that are not yet known locally from the homeserver to verify the sender of this message. */
_fetchKeyAndVerifyDecryptionResults(results, hsApi, log) {
const resultsWithoutDevice = results.filter(r => r.isVerificationUnknown);
if (resultsWithoutDevice.length) {
return log.wrap("fetch unverified senders", async log => {
const sendersWithoutDevice = Array.from(resultsWithoutDevice.reduce((senders, r) => {
return senders.add(r.encryptedEvent.sender);
}, new Set()));
log.set("senders", sendersWithoutDevice);
// fetch the devices, ignore return value,
// and just reuse _verifyDecryptionResults method so we only have one impl how to verify
await this._deviceTracker.devicesForRoomMembers(this._room.id, sendersWithoutDevice, hsApi, log);
// now that we've fetched the missing devices, try verifying the results again
const txn = await this._storage.readTxn([this._storage.storeNames.deviceIdentities]);
return this._verifyDecryptionResults(resultsWithoutDevice, txn);
const resultsWithFoundDevice = resultsWithoutDevice.filter(r => !r.isVerificationUnknown);
const resultsToEventIdMap = resultsWithFoundDevice.reduce((map, r) => {
map.set(r.encryptedEvent.event_id, r);
return map;
}, new Map());
return new BatchDecryptionResult(resultsToEventIdMap, new Map(), this);
});
} }
return new BatchDecryptionResult(new Map(), new Map(), this);
} }
async _requestMissingSessionFromBackup(senderKey, sessionId, log) { async _requestMissingSessionFromBackup(senderKey, sessionId, log) {
@ -553,6 +576,13 @@ class BatchDecryptionResult {
verifyKnownSenders(txn) { verifyKnownSenders(txn) {
return this._roomEncryption._verifyDecryptionResults(Array.from(this.results.values()), txn); return this._roomEncryption._verifyDecryptionResults(Array.from(this.results.values()), txn);
} }
/** Verify any decryption results for which we could not find a device when
* calling `verifyKnownSenders` prior, by fetching them from the homeserver.
* @returns {Promise<BatchDecryptionResult>} the results for which we found a device */
fetchAndVerifyRemainingSenders(hsApi, log) {
return this._roomEncryption._fetchKeyAndVerifyDecryptionResults(Array.from(this.results.values()), hsApi, log);
}
} }
import {createMockStorage} from "../../mocks/Storage"; import {createMockStorage} from "../../mocks/Storage";

View File

@ -75,7 +75,7 @@ export class SessionDecryption {
{encryptedRoomId: payload.room_id, eventRoomId: this.key.roomId}); {encryptedRoomId: payload.room_id, eventRoomId: this.key.roomId});
} }
replayEntries.push(new ReplayDetectionEntry(this.key.sessionId, decryptionResult!.message_index, event)); replayEntries.push(new ReplayDetectionEntry(this.key.sessionId, decryptionResult!.message_index, event));
const result = new DecryptionResult(payload, this.key.senderKey, this.key.claimedEd25519Key); const result = new DecryptionResult(payload, this.key.senderKey, this.key.claimedEd25519Key, event);
results.set(event.event_id, result); results.set(event.event_id, result);
} catch (err) { } catch (err) {
// ignore AbortError from cancelling decryption requests in dispose method // ignore AbortError from cancelling decryption requests in dispose method