diff --git a/spec/integ/crypto/crypto.spec.ts b/spec/integ/crypto/crypto.spec.ts index c81f3167e..47e0a0c6a 100644 --- a/spec/integ/crypto/crypto.spec.ts +++ b/spec/integ/crypto/crypto.spec.ts @@ -73,6 +73,7 @@ import { AddSecretStorageKeyOpts } from "../../../src/secret-storage"; import { CrossSigningKey, CryptoCallbacks, KeyBackupInfo } from "../../../src/crypto-api"; import { E2EKeyResponder } from "../../test-utils/E2EKeyResponder"; import { DecryptionError } from "../../../src/crypto/algorithms"; +import { IKeyBackup } from "../../../src/crypto/backup"; afterEach(() => { // reset fake-indexeddb after each test, to make sure we don't leak connections @@ -2635,6 +2636,60 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("crypto (%s)", (backend: string, }); describe("Manage Key Backup", () => { + beforeEach(async () => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.useRealTimers(); + }); + + it("Should be able to restore from 4S after bootstrap", async () => { + const backupVersion = "1"; + await bootstrapSecurity(backupVersion); + + const check = await aliceClient.getCrypto()!.checkKeyBackupAndEnable(); + + // Import a new key that should be uploaded + const newKey = testData.MEGOLM_SESSION_DATA; + + const awaitKeyUploaded = new Promise((resolve) => { + fetchMock.put( + "path:/_matrix/client/v3/room_keys/keys", + (url, request) => { + const uploadPayload: IKeyBackup = JSON.parse(request.body?.toString() ?? "{}"); + resolve(uploadPayload); + return { + status: 200, + body: { + count: 1, + etag: "abcdefg", + }, + }; + }, + { + overwriteRoutes: true, + }, + ); + }); + + await aliceClient.getCrypto()!.importRoomKeys([newKey]); + + // The backup loop is waiting a random amount of time to avoid different clients firing at the same time. + jest.runAllTimers(); + + const keyBackupData = await awaitKeyUploaded; + + fetchMock.get("express:/_matrix/client/v3/room_keys/keys", keyBackupData); + //should be able to restore from 4S + const importReult = await aliceClient.restoreKeyBackupWithSecretStorage( + check!.backupInfo!, + undefined, + undefined, + ); + expect(importReult.imported).toStrictEqual(1); + }); + it("Reset key backup should create a new backup and update 4S", async () => { // First set up 4S and key backup const backupVersion = "1"; diff --git a/spec/integ/crypto/megolm-backup.spec.ts b/spec/integ/crypto/megolm-backup.spec.ts index f473f1360..aad79bf35 100644 --- a/spec/integ/crypto/megolm-backup.spec.ts +++ b/spec/integ/crypto/megolm-backup.spec.ts @@ -237,6 +237,11 @@ describe.each(Object.entries(CRYPTO_BACKENDS))("megolm-keys backup (%s)", (backe expect(result.imported).toStrictEqual(1); await awaitKeyCached; + + // The key should be now cached + const afterCache = await aliceClient.restoreKeyBackupWithCache(undefined, undefined, check!.backupInfo!); + + expect(afterCache.imported).toStrictEqual(1); }); it("recover specific session from backup", async function () { diff --git a/src/client.ts b/src/client.ts index 32522d330..001e37338 100644 --- a/src/client.ts +++ b/src/client.ts @@ -3719,7 +3719,7 @@ export class MatrixClient extends TypedEventEmitter { - if (!this.crypto) { + if (!this.cryptoBackend) { throw new Error("End-to-end encryption disabled"); } const storedKey = await this.secretStorage.get("m.megolm_backup.v1");