Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save the key backup key to 4S during bootstrapCrossSigning #4542

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
41 changes: 41 additions & 0 deletions spec/unit/rust-crypto/rust-crypto.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,47 @@
expect(resetKeyBackup.mock.calls).toHaveLength(2);
});

it("bootstrapSecretStorage saves megolm backup key if already cached", async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get an integ test for this as well, please? (One which works only through the public APIs of the js-sdk, together with fetchMock)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should do the trick?

const secretStorageCallbacks = {
getSecretStorageKey: async (keys: any, name: string) => {
return [[...Object.keys(keys.keys)][0], new Uint8Array(32)];
},
} as SecretStorageCallbacks;
const secretStorage = new ServerSideSecretStorageImpl(new DummyAccountDataClient(), secretStorageCallbacks);

const rustCrypto = await makeTestRustCrypto(
{
authedRequest: jest.fn().mockImplementation((method, query) => {
if (query === "/room_keys/version") {
return Promise.resolve({ version: 1, algorithm: "dummy", auth_data: {} });
}
return Promise.resolve({});
}),
} as unknown as MatrixHttpApi<any>,
testData.TEST_USER_ID,
undefined,
secretStorage,
);

async function createSecretStorageKey() {
return {
keyInfo: {} as AddSecretStorageKeyOpts,
privateKey: new Uint8Array(32),
};
}

jest.spyOn(rustCrypto, "getSessionBackupPrivateKey").mockResolvedValue(new Uint8Array(32));
const storeSpy = jest.spyOn(secretStorage, "store");

await rustCrypto.bootstrapSecretStorage({
createSecretStorageKey,
setupNewSecretStorage: true,
setupNewKeyBackup: false,
});

expect(storeSpy).toHaveBeenCalledWith("m.megolm_backup.v1", expect.anything());

Check failure on line 746 in spec/unit/rust-crypto/rust-crypto.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node lts/*)

RustCrypto › bootstrapSecretStorage saves megolm backup key if already cached

expect(jest.fn()).toHaveBeenCalledWith(...expected) Expected: "m.megolm_backup.v1", Anything Number of calls: 0 at Object.toHaveBeenCalledWith (spec/unit/rust-crypto/rust-crypto.spec.ts:746:26) at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17) at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9)

Check failure on line 746 in spec/unit/rust-crypto/rust-crypto.spec.ts

View workflow job for this annotation

GitHub Actions / Jest [unit] (Node 22)

RustCrypto › bootstrapSecretStorage saves megolm backup key if already cached

expect(jest.fn()).toHaveBeenCalledWith(...expected) Expected: "m.megolm_backup.v1", Anything Number of calls: 0 at Object.toHaveBeenCalledWith (spec/unit/rust-crypto/rust-crypto.spec.ts:746:26) at asyncGeneratorStep (node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17) at _next (node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9)
});

it("isSecretStorageReady", async () => {
const mockSecretStorage = {
getDefaultKeyId: jest.fn().mockResolvedValue(null),
Expand Down
15 changes: 14 additions & 1 deletion src/rust-crypto/rust-crypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,20 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
await this.secretStorage.store("m.cross_signing.self_signing", crossSigningPrivateKeys.self_signing_key);
}

if (setupNewKeyBackup) {
// likewise with the key backup key: if we have one, store it in secret storage (if it's not already there)
// also don't bother storing it if we're about to set up a new backup
if (!setupNewKeyBackup) {
const backupKeys: RustSdkCryptoJs.BackupKeys = await this.olmMachine.getBackupKeys();
if (backupKeys.decryptionKey) {
const keyBackupKeyInStorage = await secretStorageCanAccessSecrets(this.secretStorage, [
"m.megolm_backup.v1",
]);

if (!keyBackupKeyInStorage) {
await this.secretStorage.store("m.megolm_backup.v1", backupKeys.decryptionKey.toBase64());
}
}
} else {
await this.resetKeyBackup();
}
}
Expand Down
Loading