diff --git a/spec/integ/crypto/rust-crypto.spec.ts b/spec/integ/crypto/rust-crypto.spec.ts index c36287668..3f0193b02 100644 --- a/spec/integ/crypto/rust-crypto.spec.ts +++ b/spec/integ/crypto/rust-crypto.spec.ts @@ -41,7 +41,7 @@ describe("MatrixClient.initRustCrypto", () => { await expect(() => unknownDeviceClient.initRustCrypto()).rejects.toThrow("unknown deviceId"); }); - it("should create the indexed dbs", async () => { + it("should create the indexed db", async () => { const matrixClient = createClient({ baseUrl: "http://test.server", userId: "@alice:localhost", @@ -53,7 +53,25 @@ describe("MatrixClient.initRustCrypto", () => { await matrixClient.initRustCrypto(); - // should have two dbs now + // should have an indexed db now + const databaseNames = (await indexedDB.databases()).map((db) => db.name); + expect(databaseNames).toEqual(expect.arrayContaining(["matrix-js-sdk::matrix-sdk-crypto"])); + }); + + it("should create the meta db if given a pickleKey", async () => { + const matrixClient = createClient({ + baseUrl: "http://test.server", + userId: "@alice:localhost", + deviceId: "aliceDevice", + pickleKey: "testKey", + }); + + // No databases. + expect(await indexedDB.databases()).toHaveLength(0); + + await matrixClient.initRustCrypto(); + + // should have two indexed dbs now const databaseNames = (await indexedDB.databases()).map((db) => db.name); expect(databaseNames).toEqual( expect.arrayContaining(["matrix-js-sdk::matrix-sdk-crypto", "matrix-js-sdk::matrix-sdk-crypto-meta"]), @@ -78,6 +96,7 @@ describe("MatrixClient.clearStores", () => { baseUrl: "http://test.server", userId: "@alice:localhost", deviceId: "aliceDevice", + pickleKey: "testKey", }); await matrixClient.initRustCrypto(); diff --git a/spec/unit/rust-crypto/rust-crypto.spec.ts b/spec/unit/rust-crypto/rust-crypto.spec.ts index c0afcc524..85f746447 100644 --- a/spec/unit/rust-crypto/rust-crypto.spec.ts +++ b/spec/unit/rust-crypto/rust-crypto.spec.ts @@ -54,6 +54,56 @@ const TEST_DEVICE_ID = "TEST_DEVICE"; afterEach(() => { fetchMock.reset(); + jest.restoreAllMocks(); +}); + +describe("initRustCrypto", () => { + function makeTestOlmMachine(): Mocked { + return { + registerRoomKeyUpdatedCallback: jest.fn(), + registerUserIdentityUpdatedCallback: jest.fn(), + outgoingRequests: jest.fn(), + } as unknown as Mocked; + } + + it("passes through the store params", async () => { + const testOlmMachine = makeTestOlmMachine(); + jest.spyOn(OlmMachine, "initialize").mockResolvedValue(testOlmMachine); + + await initRustCrypto( + {} as MatrixClient["http"], + TEST_USER, + TEST_DEVICE_ID, + {} as ServerSideSecretStorage, + {} as CryptoCallbacks, + "storePrefix", + "storePassphrase", + ); + + expect(OlmMachine.initialize).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + "storePrefix", + "storePassphrase", + ); + }); + + it("suppresses the storePassphrase if storePrefix is unset", async () => { + const testOlmMachine = makeTestOlmMachine(); + jest.spyOn(OlmMachine, "initialize").mockResolvedValue(testOlmMachine); + + await initRustCrypto( + {} as MatrixClient["http"], + TEST_USER, + TEST_DEVICE_ID, + {} as ServerSideSecretStorage, + {} as CryptoCallbacks, + null, + "storePassphrase", + ); + + expect(OlmMachine.initialize).toHaveBeenCalledWith(expect.anything(), expect.anything(), undefined, undefined); + }); }); describe("RustCrypto", () => { @@ -398,10 +448,6 @@ describe("RustCrypto", () => { ); }); - afterEach(() => { - jest.restoreAllMocks(); - }); - async function makeEncryptedEvent(): Promise { const encryptedEvent = mkEvent({ event: true, @@ -812,5 +858,5 @@ async function makeTestRustCrypto( secretStorage: ServerSideSecretStorage = {} as ServerSideSecretStorage, cryptoCallbacks: CryptoCallbacks = {} as CryptoCallbacks, ): Promise { - return await initRustCrypto(http, userId, deviceId, secretStorage, cryptoCallbacks, null); + return await initRustCrypto(http, userId, deviceId, secretStorage, cryptoCallbacks, null, undefined); } diff --git a/src/client.ts b/src/client.ts index c6c4b9299..69f21560b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -343,7 +343,14 @@ export interface ICreateClientOpts { deviceToImport?: IExportedDevice; /** - * Key used to pickle olm objects or other sensitive data. + * Encryption key used for encrypting sensitive data (such as e2ee keys) in storage. + * + * This must be set to the same value every time the client is initialised for the same device. + * + * If unset, either a hardcoded key or no encryption at all is used, depending on the Crypto implementation. + * + * No particular requirement is placed on the key data (it is fed into an HKDF to generate the actual encryption + * keys). */ pickleKey?: string; @@ -1193,7 +1200,18 @@ export class MatrixClient extends TypedEventEmitter { // initialise the rust matrix-sdk-crypto-wasm, if it hasn't already been done await RustSdkCryptoJs.initAsync(); @@ -59,7 +63,7 @@ export async function initRustCrypto( u, d, storePrefix ?? undefined, - (storePrefix && "test pass") ?? undefined, + (storePrefix && storePassphrase) ?? undefined, ); const rustCrypto = new RustCrypto(olmMachine, http, userId, deviceId, secretStorage, cryptoCallbacks); await olmMachine.registerRoomKeyUpdatedCallback((sessions: RustSdkCryptoJs.RoomKeyInfo[]) =>