1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-23 17:02:25 +03:00

Add disableKeyStorage() to crypto API (#4742)

* Add disableKeyStorage() to crypto API

As an all-in-one method for deleting all server side key storage on
the user's account (as the doc hopefully explains).

* Add test

* const

* Can't be disabled here
This commit is contained in:
David Baker
2025-03-06 11:16:28 +00:00
committed by GitHub
parent 3e512711d7
commit db7e3e3cf3
3 changed files with 84 additions and 11 deletions

View File

@@ -2318,6 +2318,43 @@ describe("RustCrypto", () => {
expect(dehydratedDeviceIsDeleted).toBeTruthy(); expect(dehydratedDeviceIsDeleted).toBeTruthy();
}); });
}); });
describe("disableKeyStorage", () => {
it("should disable key storage", async () => {
const secretStorage = {
getDefaultKeyId: jest.fn().mockResolvedValue("bloop"),
setDefaultKeyId: jest.fn(),
store: jest.fn(),
} as unknown as ServerSideSecretStorage;
fetchMock.get("path:/_matrix/client/v3/room_keys/version", testData.SIGNED_BACKUP_DATA);
let backupIsDeleted = false;
fetchMock.delete("path:/_matrix/client/v3/room_keys/version/1", () => {
backupIsDeleted = true;
return {};
});
let dehydratedDeviceIsDeleted = false;
fetchMock.delete("path:/_matrix/client/unstable/org.matrix.msc3814.v1/dehydrated_device", () => {
dehydratedDeviceIsDeleted = true;
return { device_id: "ADEVICEID" };
});
const rustCrypto = await makeTestRustCrypto(makeMatrixHttpApi(), undefined, undefined, secretStorage);
await rustCrypto.disableKeyStorage();
expect(secretStorage.store).toHaveBeenCalledWith("m.cross_signing.master", null);
expect(secretStorage.store).toHaveBeenCalledWith("m.cross_signing.self_signing", null);
expect(secretStorage.store).toHaveBeenCalledWith("m.cross_signing.user_signing", null);
expect(secretStorage.store).toHaveBeenCalledWith("m.megolm_backup.v1", null);
expect(secretStorage.store).toHaveBeenCalledWith("m.secret_storage.key.bloop", null);
expect(secretStorage.setDefaultKeyId).toHaveBeenCalledWith(null);
expect(backupIsDeleted).toBeTruthy();
expect(dehydratedDeviceIsDeleted).toBeTruthy();
});
});
}); });
/** Build a MatrixHttpApi instance */ /** Build a MatrixHttpApi instance */

View File

@@ -629,6 +629,16 @@ export interface CryptoApi {
*/ */
resetKeyBackup(): Promise<void>; resetKeyBackup(): Promise<void>;
/**
* Disables server-side key storage and deletes server-side backups.
* * Deletes the current key backup version, if any (but not any previous versions).
* * Disables 4S, deleting the info for the default key, the default key pointer itself and any
* known 4S data (cross-signing keys and the megolm key backup key).
* * Deletes any dehydrated devices.
* * Sets the "m.org.matrix.custom.backup_disabled" account data flag to indicate that the user has disabled backups.
*/
disableKeyStorage(): Promise<void>;
/** /**
* Deletes the given key backup. * Deletes the given key backup.
* *

View File

@@ -1276,6 +1276,24 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
this.checkKeyBackupAndEnable(); this.checkKeyBackupAndEnable();
} }
/**
* Implementation of {@link CryptoApi#disableKeyStorage}.
*/
public async disableKeyStorage(): Promise<void> {
// Get the key backup version we're using
const info = await this.getKeyBackupInfo();
if (info?.version) {
await this.deleteKeyBackupVersion(info.version);
} else {
logger.error("Can't delete key backup version: no version available");
}
// also turn off 4S, since this is also storing keys on the server.
await this.deleteSecretStorage();
await this.dehydratedDeviceManager.delete();
}
/** /**
* Signs the given object with the current device and current identity (if available). * Signs the given object with the current device and current identity (if available).
* As defined in {@link https://spec.matrix.org/v1.8/appendices/#signing-json | Signing JSON}. * As defined in {@link https://spec.matrix.org/v1.8/appendices/#signing-json | Signing JSON}.
@@ -1447,17 +1465,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
// Disable backup, and delete all the backups from the server // Disable backup, and delete all the backups from the server
await this.backupManager.deleteAllKeyBackupVersions(); await this.backupManager.deleteAllKeyBackupVersions();
// Remove the stored secrets in the secret storage this.deleteSecretStorage();
await this.secretStorage.store("m.cross_signing.master", null);
await this.secretStorage.store("m.cross_signing.self_signing", null);
await this.secretStorage.store("m.cross_signing.user_signing", null);
await this.secretStorage.store("m.megolm_backup.v1", null);
// Remove the recovery key
const defaultKeyId = await this.secretStorage.getDefaultKeyId();
if (defaultKeyId) await this.secretStorage.store(`m.secret_storage.key.${defaultKeyId}`, null);
// Disable the recovery key and the secret storage
await this.secretStorage.setDefaultKeyId(null);
// Reset the cross-signing keys // Reset the cross-signing keys
await this.crossSigningIdentity.bootstrapCrossSigning({ await this.crossSigningIdentity.bootstrapCrossSigning({
@@ -1471,6 +1479,24 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventH
this.logger.debug("resetEncryption: ended"); this.logger.debug("resetEncryption: ended");
} }
/**
* Removes the secret storage key, default key pointer and all (known) secret storage data
* from the user's account data
*/
private async deleteSecretStorage(): Promise<void> {
// Remove the stored secrets in the secret storage
await this.secretStorage.store("m.cross_signing.master", null);
await this.secretStorage.store("m.cross_signing.self_signing", null);
await this.secretStorage.store("m.cross_signing.user_signing", null);
await this.secretStorage.store("m.megolm_backup.v1", null);
// Remove the recovery key
const defaultKeyId = await this.secretStorage.getDefaultKeyId();
if (defaultKeyId) await this.secretStorage.store(`m.secret_storage.key.${defaultKeyId}`, null);
// Disable the recovery key and the secret storage
await this.secretStorage.setDefaultKeyId(null);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// //
// SyncCryptoCallbacks implementation // SyncCryptoCallbacks implementation