From 6168cedf32e8a4c71c9ebc8c36bd33dd62a62c01 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Tue, 3 Jan 2023 11:06:54 -0500 Subject: [PATCH] Avoid triggering decryption errors when decrypting redacted events (#3004) --- spec/unit/crypto.spec.ts | 32 ++++++++++++++++++++++++++++++++ src/crypto/index.ts | 15 +++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/spec/unit/crypto.spec.ts b/spec/unit/crypto.spec.ts index 3b7689ca0ce..36a74607840 100644 --- a/spec/unit/crypto.spec.ts +++ b/spec/unit/crypto.spec.ts @@ -167,6 +167,38 @@ describe("Crypto", function () { client.stopClient(); }); + + it("doesn't throw an error when attempting to decrypt a redacted event", async () => { + const client = new TestClient("@alice:example.com", "deviceid").client; + await client.initCrypto(); + + const event = new MatrixEvent({ + content: {}, + event_id: "$event_id", + room_id: "!room_id", + sender: "@bob:example.com", + type: "m.room.encrypted", + unsigned: { + redacted_because: { + content: {}, + event_id: "$redaction_event_id", + redacts: "$event_id", + room_id: "!room_id", + origin_server_ts: 1234567890, + sender: "@bob:example.com", + type: "m.room.redaction", + unsigned: {}, + }, + }, + }); + await event.attemptDecryption(client.crypto!); + expect(event.isDecryptionFailure()).toBeFalsy(); + // since the redaction event isn't encrypted, the redacted_because + // should be the same as in the original event + expect(event.getRedactionEvent()).toEqual(event.getUnsigned().redacted_because); + + client.stopClient(); + }); }); describe("Session management", function () { diff --git a/src/crypto/index.ts b/src/crypto/index.ts index fe8719a4c4a..24b36b08143 100644 --- a/src/crypto/index.ts +++ b/src/crypto/index.ts @@ -2878,11 +2878,22 @@ export class Crypto extends TypedEventEmitter { if (event.isRedacted()) { + // Try to decrypt the redaction event, to support encrypted + // redaction reasons. If we can't decrypt, just fall back to using + // the original redacted_because. const redactionEvent = new MatrixEvent({ room_id: event.getRoomId(), ...event.getUnsigned().redacted_because, }); - const decryptedEvent = await this.decryptEvent(redactionEvent); + let redactedBecause: IEvent = event.getUnsigned().redacted_because!; + if (redactionEvent.isEncrypted()) { + try { + const decryptedEvent = await this.decryptEvent(redactionEvent); + redactedBecause = decryptedEvent.clearEvent as IEvent; + } catch (e) { + logger.warn("Decryption of redaction failed. Falling back to unencrypted event.", e); + } + } return { clearEvent: { @@ -2890,7 +2901,7 @@ export class Crypto extends TypedEventEmitter