You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Clean up code for handling decryption failures (#4126)
Various improvements, including: * Defining an enum for decryption failure reasons * Exposing the reason code as a property on Event
This commit is contained in:
committed by
GitHub
parent
a573727662
commit
d1259b241c
@ -80,12 +80,12 @@ import { SecretStorageKeyDescription } from "../../../src/secret-storage";
|
||||
import {
|
||||
CrossSigningKey,
|
||||
CryptoCallbacks,
|
||||
DecryptionFailureCode,
|
||||
EventShieldColour,
|
||||
EventShieldReason,
|
||||
KeyBackupInfo,
|
||||
} from "../../../src/crypto-api";
|
||||
import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder";
|
||||
import { DecryptionError } from "../../../src/crypto/algorithms";
|
||||
import { IKeyBackup } from "../../../src/crypto/backup";
|
||||
import {
|
||||
createOlmAccount,
|
||||
@ -470,9 +470,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const awaitUISI = new Promise<void>((resolve) => {
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||
const error = err as DecryptionError;
|
||||
if (error.code == "MEGOLM_UNKNOWN_INBOUND_SESSION_ID") {
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev) => {
|
||||
if (ev.decryptionFailureReason === DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
@ -499,9 +498,8 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
await startClientAndAwaitFirstSync();
|
||||
|
||||
const awaitUnknownIndex = new Promise<void>((resolve) => {
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||
const error = err as DecryptionError;
|
||||
if (error.code == "OLM_UNKNOWN_MESSAGE_INDEX") {
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev) => {
|
||||
if (ev.decryptionFailureReason === DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
@ -532,13 +530,12 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string,
|
||||
await aliceClient.getCrypto()!.importRoomKeys([testData.MEGOLM_SESSION_DATA]);
|
||||
|
||||
const awaitDecryptionError = new Promise<void>((resolve) => {
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev, err) => {
|
||||
const error = err as DecryptionError;
|
||||
aliceClient.on(MatrixEventEvent.Decrypted, (ev) => {
|
||||
// rust and libolm can't have an exact 1:1 mapping for all errors,
|
||||
// but some errors are part of API and should match
|
||||
if (
|
||||
error.code != "MEGOLM_UNKNOWN_INBOUND_SESSION_ID" &&
|
||||
error.code != "OLM_UNKNOWN_MESSAGE_INDEX"
|
||||
ev.decryptionFailureReason !== DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID &&
|
||||
ev.decryptionFailureReason !== DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX
|
||||
) {
|
||||
resolve();
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ import {
|
||||
THREAD_RELATION_TYPE,
|
||||
TweakName,
|
||||
} from "../../../src";
|
||||
import { DecryptionFailureCode } from "../../../src/crypto-api";
|
||||
import { DecryptionError } from "../../../src/common-crypto/CryptoBackend";
|
||||
|
||||
describe("MatrixEvent", () => {
|
||||
it("should create copies of itself", () => {
|
||||
@ -360,20 +362,50 @@ describe("MatrixEvent", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("should report decryption errors", async () => {
|
||||
it("should report unknown decryption errors", async () => {
|
||||
const decryptionListener = jest.fn();
|
||||
encryptedEvent.addListener(MatrixEventEvent.Decrypted, decryptionListener);
|
||||
|
||||
const testError = new Error("test error");
|
||||
const crypto = {
|
||||
decryptEvent: jest.fn().mockRejectedValue(new Error("test error")),
|
||||
decryptEvent: jest.fn().mockRejectedValue(testError),
|
||||
} as unknown as Crypto;
|
||||
|
||||
await encryptedEvent.attemptDecryption(crypto);
|
||||
expect(encryptedEvent.isEncrypted()).toBeTruthy();
|
||||
expect(encryptedEvent.isBeingDecrypted()).toBeFalsy();
|
||||
expect(encryptedEvent.isDecryptionFailure()).toBeTruthy();
|
||||
expect(encryptedEvent.decryptionFailureReason).toEqual(DecryptionFailureCode.UNKNOWN_ERROR);
|
||||
expect(encryptedEvent.isEncryptedDisabledForUnverifiedDevices).toBeFalsy();
|
||||
expect(encryptedEvent.getContent()).toEqual({
|
||||
msgtype: "m.bad.encrypted",
|
||||
body: "** Unable to decrypt: Error: test error **",
|
||||
});
|
||||
expect(decryptionListener).toHaveBeenCalledWith(encryptedEvent, testError);
|
||||
});
|
||||
|
||||
it("should report known decryption errors", async () => {
|
||||
const decryptionListener = jest.fn();
|
||||
encryptedEvent.addListener(MatrixEventEvent.Decrypted, decryptionListener);
|
||||
|
||||
const testError = new DecryptionError(DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID, "uisi");
|
||||
const crypto = {
|
||||
decryptEvent: jest.fn().mockRejectedValue(testError),
|
||||
} as unknown as Crypto;
|
||||
|
||||
await encryptedEvent.attemptDecryption(crypto);
|
||||
expect(encryptedEvent.isEncrypted()).toBeTruthy();
|
||||
expect(encryptedEvent.isBeingDecrypted()).toBeFalsy();
|
||||
expect(encryptedEvent.isDecryptionFailure()).toBeTruthy();
|
||||
expect(encryptedEvent.decryptionFailureReason).toEqual(
|
||||
DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID,
|
||||
);
|
||||
expect(encryptedEvent.isEncryptedDisabledForUnverifiedDevices).toBeFalsy();
|
||||
expect(encryptedEvent.getContent()).toEqual({
|
||||
msgtype: "m.bad.encrypted",
|
||||
body: "** Unable to decrypt: DecryptionError: uisi **",
|
||||
});
|
||||
expect(decryptionListener).toHaveBeenCalledWith(encryptedEvent, testError);
|
||||
});
|
||||
|
||||
it(`should report "DecryptionError: The sender has disabled encrypting to unverified devices."`, async () => {
|
||||
@ -423,6 +455,8 @@ describe("MatrixEvent", () => {
|
||||
expect(eventAttemptDecryptionSpy).toHaveBeenCalledTimes(2);
|
||||
expect(crypto.decryptEvent).toHaveBeenCalledTimes(2);
|
||||
expect(encryptedEvent.getType()).toEqual("m.room.message");
|
||||
expect(encryptedEvent.isDecryptionFailure()).toBe(false);
|
||||
expect(encryptedEvent.decryptionFailureReason).toBe(null);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -25,10 +25,11 @@ import { EventType, RelationType, UNSTABLE_MSC2716_MARKER } from "../../src/@typ
|
||||
import { MatrixEvent, MatrixEventEvent } from "../../src/models/event";
|
||||
import { M_BEACON } from "../../src/@types/beacon";
|
||||
import { MatrixClient } from "../../src/client";
|
||||
import { DecryptionError } from "../../src/crypto/algorithms";
|
||||
import { defer } from "../../src/utils";
|
||||
import { Room } from "../../src/models/room";
|
||||
import { KnownMembership } from "../../src/@types/membership";
|
||||
import { DecryptionFailureCode } from "../../src/crypto-api";
|
||||
import { DecryptionError } from "../../src/common-crypto/CryptoBackend";
|
||||
|
||||
describe("RoomState", function () {
|
||||
const roomId = "!foo:bar";
|
||||
@ -1040,7 +1041,9 @@ describe("RoomState", function () {
|
||||
content: beacon1RelationContent,
|
||||
});
|
||||
jest.spyOn(failedDecryptionRelatedEvent, "isDecryptionFailure").mockReturnValue(true);
|
||||
mockClient.decryptEventIfNeeded.mockRejectedValue(new DecryptionError("ERR", "msg"));
|
||||
mockClient.decryptEventIfNeeded.mockRejectedValue(
|
||||
new DecryptionError(DecryptionFailureCode.UNKNOWN_ERROR, "msg"),
|
||||
);
|
||||
// spy on event.once
|
||||
const eventOnceSpy = jest.spyOn(failedDecryptionRelatedEvent, "once");
|
||||
|
||||
|
@ -16,6 +16,7 @@ limitations under the License.
|
||||
|
||||
import { mkDecryptionFailureMatrixEvent, mkEncryptedMatrixEvent, mkMatrixEvent } from "../../src/testing";
|
||||
import { EventType } from "../../src";
|
||||
import { DecryptionFailureCode } from "../../src/crypto-api";
|
||||
|
||||
describe("testing", () => {
|
||||
describe("mkMatrixEvent", () => {
|
||||
@ -60,6 +61,7 @@ describe("testing", () => {
|
||||
expect(event.sender?.userId).toEqual("@alice:test");
|
||||
expect(event.isEncrypted()).toBe(true);
|
||||
expect(event.isDecryptionFailure()).toBe(false);
|
||||
expect(event.decryptionFailureReason).toBe(null);
|
||||
expect(event.getContent()).toEqual({ body: "blah" });
|
||||
expect(event.getType()).toEqual("m.room.message");
|
||||
});
|
||||
@ -70,13 +72,14 @@ describe("testing", () => {
|
||||
const event = await mkDecryptionFailureMatrixEvent({
|
||||
sender: "@alice:test",
|
||||
roomId: "!test:room",
|
||||
code: "UNKNOWN",
|
||||
code: DecryptionFailureCode.UNKNOWN_ERROR,
|
||||
msg: "blah",
|
||||
});
|
||||
|
||||
expect(event.sender?.userId).toEqual("@alice:test");
|
||||
expect(event.isEncrypted()).toBe(true);
|
||||
expect(event.isDecryptionFailure()).toBe(true);
|
||||
expect(event.decryptionFailureReason).toEqual(DecryptionFailureCode.UNKNOWN_ERROR);
|
||||
expect(event.getContent()).toEqual({
|
||||
body: "** Unable to decrypt: DecryptionError: blah **",
|
||||
msgtype: "m.bad.encrypted",
|
||||
|
Reference in New Issue
Block a user