You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-30 04:23:07 +03:00
Don't back up keys that we got from backup (#3934)
* don't back up keys that we got from backup * lint * lint again * remove key source struct and add function for importing from backup * apply changes from review --------- Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
@ -51,6 +51,7 @@ import * as testData from "../../test-utils/test-data";
|
|||||||
import { defer } from "../../../src/utils";
|
import { defer } from "../../../src/utils";
|
||||||
import { logger } from "../../../src/logger";
|
import { logger } from "../../../src/logger";
|
||||||
import { OutgoingRequestsManager } from "../../../src/rust-crypto/OutgoingRequestsManager";
|
import { OutgoingRequestsManager } from "../../../src/rust-crypto/OutgoingRequestsManager";
|
||||||
|
import { Curve25519AuthData } from "../../../src/crypto-api/keybackup";
|
||||||
|
|
||||||
const TEST_USER = "@alice:example.com";
|
const TEST_USER = "@alice:example.com";
|
||||||
const TEST_DEVICE_ID = "TEST_DEVICE";
|
const TEST_DEVICE_ID = "TEST_DEVICE";
|
||||||
@ -931,6 +932,48 @@ describe("RustCrypto", () => {
|
|||||||
await rustCrypto.onUserIdentityUpdated(new RustSdkCryptoJs.UserId(testData.TEST_USER_ID));
|
await rustCrypto.onUserIdentityUpdated(new RustSdkCryptoJs.UserId(testData.TEST_USER_ID));
|
||||||
expect(await keyBackupStatusPromise).toBe(true);
|
expect(await keyBackupStatusPromise).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not back up keys that came from backup", async () => {
|
||||||
|
const rustCrypto = await makeTestRustCrypto();
|
||||||
|
const olmMachine: OlmMachine = rustCrypto["olmMachine"];
|
||||||
|
|
||||||
|
await olmMachine.enableBackupV1(
|
||||||
|
(testData.SIGNED_BACKUP_DATA.auth_data as Curve25519AuthData).public_key,
|
||||||
|
testData.SIGNED_BACKUP_DATA.version!,
|
||||||
|
);
|
||||||
|
|
||||||
|
// we import two keys: one "from backup", and one "from export"
|
||||||
|
const [backedUpRoomKey, exportedRoomKey] = testData.MEGOLM_SESSION_DATA_ARRAY;
|
||||||
|
await rustCrypto.importBackedUpRoomKeys([backedUpRoomKey]);
|
||||||
|
await rustCrypto.importRoomKeys([exportedRoomKey]);
|
||||||
|
|
||||||
|
// we ask for the keys that should be backed up
|
||||||
|
const roomKeysRequest = await olmMachine.backupRoomKeys();
|
||||||
|
expect(roomKeysRequest).toBeTruthy();
|
||||||
|
const roomKeys = JSON.parse(roomKeysRequest!.body);
|
||||||
|
|
||||||
|
// we expect that the key "from export" is present
|
||||||
|
expect(roomKeys).toMatchObject({
|
||||||
|
rooms: {
|
||||||
|
[exportedRoomKey.room_id]: {
|
||||||
|
sessions: {
|
||||||
|
[exportedRoomKey.session_id]: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// we expect that the key "from backup" is not present
|
||||||
|
expect(roomKeys).not.toMatchObject({
|
||||||
|
rooms: {
|
||||||
|
[backedUpRoomKey.room_id]: {
|
||||||
|
sessions: {
|
||||||
|
[backedUpRoomKey.session_id]: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3984,10 +3984,9 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
backupDecryptor.free();
|
backupDecryptor.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.cryptoBackend.importRoomKeys(keys, {
|
await this.cryptoBackend.importBackedUpRoomKeys(keys, {
|
||||||
progressCallback,
|
progressCallback,
|
||||||
untrusted,
|
untrusted,
|
||||||
source: "backup",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// in case entering the passphrase would add a new signature?
|
/// in case entering the passphrase would add a new signature?
|
||||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator";
|
||||||
import { IClearEvent, MatrixEvent } from "../models/event";
|
import { IClearEvent, MatrixEvent } from "../models/event";
|
||||||
import { Room } from "../models/room";
|
import { Room } from "../models/room";
|
||||||
import { CryptoApi } from "../crypto-api";
|
import { CryptoApi, ImportRoomKeysOpts } from "../crypto-api";
|
||||||
import { CrossSigningInfo, UserTrustLevel } from "../crypto/CrossSigning";
|
import { CrossSigningInfo, UserTrustLevel } from "../crypto/CrossSigning";
|
||||||
import { IEncryptedEventInfo } from "../crypto/api";
|
import { IEncryptedEventInfo } from "../crypto/api";
|
||||||
import { KeyBackupInfo, KeyBackupSession } from "../crypto-api/keybackup";
|
import { KeyBackupInfo, KeyBackupSession } from "../crypto-api/keybackup";
|
||||||
@ -108,6 +108,15 @@ export interface CryptoBackend extends SyncCryptoCallbacks, CryptoApi {
|
|||||||
* @param privKey - The private decryption key.
|
* @param privKey - The private decryption key.
|
||||||
*/
|
*/
|
||||||
getBackupDecryptor(backupInfo: KeyBackupInfo, privKey: ArrayLike<number>): Promise<BackupDecryptor>;
|
getBackupDecryptor(backupInfo: KeyBackupInfo, privKey: ArrayLike<number>): Promise<BackupDecryptor>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import a list of room keys restored from backup
|
||||||
|
*
|
||||||
|
* @param keys - a list of session export objects
|
||||||
|
* @param opts - options object
|
||||||
|
* @returns a promise which resolves once the keys have been imported
|
||||||
|
*/
|
||||||
|
importBackedUpRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The methods which crypto implementations should expose to the Sync api
|
/** The methods which crypto implementations should expose to the Sync api
|
||||||
|
@ -597,9 +597,10 @@ export interface ImportRoomKeyProgressData {
|
|||||||
export interface ImportRoomKeysOpts {
|
export interface ImportRoomKeysOpts {
|
||||||
/** Reports ongoing progress of the import process. Can be used for feedback. */
|
/** Reports ongoing progress of the import process. Can be used for feedback. */
|
||||||
progressCallback?: (stage: ImportRoomKeyProgressData) => void;
|
progressCallback?: (stage: ImportRoomKeyProgressData) => void;
|
||||||
// TODO, the rust SDK will always such imported keys as untrusted
|
/** @deprecated the rust SDK will always such imported keys as untrusted */
|
||||||
untrusted?: boolean;
|
untrusted?: boolean;
|
||||||
source?: String; // TODO: Enum (backup, file, ??)
|
/** @deprecated not useful externally */
|
||||||
|
source?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1897,6 +1897,14 @@ export class Crypto extends TypedEventEmitter<CryptoEvent, CryptoEventHandlerMap
|
|||||||
return new LibOlmBackupDecryptor(algorithm);
|
return new LibOlmBackupDecryptor(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link CryptoBackend#importBackedUpRoomKeys}.
|
||||||
|
*/
|
||||||
|
public importBackedUpRoomKeys(keys: IMegolmSessionData[], opts: ImportRoomKeysOpts = {}): Promise<void> {
|
||||||
|
opts.source = "backup";
|
||||||
|
return this.importRoomKeys(keys, opts);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a set of keys as our own, trusted, cross-signing keys.
|
* Store a set of keys as our own, trusted, cross-signing keys.
|
||||||
*
|
*
|
||||||
|
@ -225,7 +225,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
for (const k of keys) {
|
for (const k of keys) {
|
||||||
k.room_id = targetRoomId;
|
k.room_id = targetRoomId;
|
||||||
}
|
}
|
||||||
await this.importRoomKeys(keys);
|
await this.importBackedUpRoomKeys(keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -409,9 +409,8 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async importRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void> {
|
public async importRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void> {
|
||||||
// TODO when backup support will be added we would need to expose the `from_backup` flag in the bindings
|
|
||||||
const jsonKeys = JSON.stringify(keys);
|
const jsonKeys = JSON.stringify(keys);
|
||||||
await this.olmMachine.importRoomKeys(jsonKeys, (progress: BigInt, total: BigInt) => {
|
await this.olmMachine.importExportedRoomKeys(jsonKeys, (progress: BigInt, total: BigInt): void => {
|
||||||
const importOpt: ImportRoomKeyProgressData = {
|
const importOpt: ImportRoomKeyProgressData = {
|
||||||
total: Number(total),
|
total: Number(total),
|
||||||
successes: Number(progress),
|
successes: Number(progress),
|
||||||
@ -1265,6 +1264,29 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
return new RustBackupDecryptor(backupDecryptionKey);
|
return new RustBackupDecryptor(backupDecryptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@link CryptoBackend#importBackedUpRoomKeys}.
|
||||||
|
*/
|
||||||
|
public async importBackedUpRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void> {
|
||||||
|
const keysByRoom: Map<RustSdkCryptoJs.RoomId, Map<string, IMegolmSessionData>> = new Map();
|
||||||
|
for (const key of keys) {
|
||||||
|
const roomId = new RustSdkCryptoJs.RoomId(key.room_id);
|
||||||
|
if (!keysByRoom.has(roomId)) {
|
||||||
|
keysByRoom.set(roomId, new Map());
|
||||||
|
}
|
||||||
|
keysByRoom.get(roomId)!.set(key.session_id, key);
|
||||||
|
}
|
||||||
|
await this.olmMachine.importBackedUpRoomKeys(keysByRoom, (progress: BigInt, total: BigInt): void => {
|
||||||
|
const importOpt: ImportRoomKeyProgressData = {
|
||||||
|
total: Number(total),
|
||||||
|
successes: Number(progress),
|
||||||
|
stage: "load_keys",
|
||||||
|
failures: 0,
|
||||||
|
};
|
||||||
|
opts?.progressCallback?.(importOpt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// SyncCryptoCallbacks implementation
|
// SyncCryptoCallbacks implementation
|
||||||
|
Reference in New Issue
Block a user