You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Element-R: implement {get,store}SessionBackupPrivateKey
(#3622)
This commit is contained in:
committed by
GitHub
parent
29b815b678
commit
0e95df5dba
@ -55,7 +55,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@matrix-org/matrix-sdk-crypto-wasm": "^1.0.1",
|
"@matrix-org/matrix-sdk-crypto-wasm": "^1.1.0",
|
||||||
"another-json": "^0.2.0",
|
"another-json": "^0.2.0",
|
||||||
"bs58": "^5.0.0",
|
"bs58": "^5.0.0",
|
||||||
"content-type": "^1.0.4",
|
"content-type": "^1.0.4",
|
||||||
|
@ -503,6 +503,16 @@ describe("RustCrypto", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("get|storeSessionBackupPrivateKey", () => {
|
||||||
|
it("can save and restore a key", async () => {
|
||||||
|
const key = "testtesttesttesttesttesttesttest";
|
||||||
|
const rustCrypto = await makeTestRustCrypto();
|
||||||
|
await rustCrypto.storeSessionBackupPrivateKey(new TextEncoder().encode(key));
|
||||||
|
const fetched = await rustCrypto.getSessionBackupPrivateKey();
|
||||||
|
expect(new TextDecoder().decode(fetched!)).toEqual(key);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/** build a basic RustCrypto instance for testing
|
/** build a basic RustCrypto instance for testing
|
||||||
|
@ -3726,10 +3726,10 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
backupInfo: IKeyBackupInfo,
|
backupInfo: IKeyBackupInfo,
|
||||||
opts?: IKeyBackupRestoreOpts,
|
opts?: IKeyBackupRestoreOpts,
|
||||||
): Promise<IKeyBackupRestoreResult> {
|
): Promise<IKeyBackupRestoreResult> {
|
||||||
if (!this.crypto) {
|
if (!this.cryptoBackend) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
const privKey = await this.crypto.getSessionBackupPrivateKey();
|
const privKey = await this.cryptoBackend.getSessionBackupPrivateKey();
|
||||||
if (!privKey) {
|
if (!privKey) {
|
||||||
throw new Error("Couldn't get key");
|
throw new Error("Couldn't get key");
|
||||||
}
|
}
|
||||||
@ -3767,7 +3767,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
const cacheCompleteCallback = opts?.cacheCompleteCallback;
|
const cacheCompleteCallback = opts?.cacheCompleteCallback;
|
||||||
const progressCallback = opts?.progressCallback;
|
const progressCallback = opts?.progressCallback;
|
||||||
|
|
||||||
if (!this.crypto) {
|
if (!this.cryptoBackend) {
|
||||||
throw new Error("End-to-end encryption disabled");
|
throw new Error("End-to-end encryption disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3790,9 +3790,13 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
return Promise.reject(new MatrixError({ errcode: MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY }));
|
return Promise.reject(new MatrixError({ errcode: MatrixClient.RESTORE_BACKUP_ERROR_BAD_KEY }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(privKey instanceof Uint8Array)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
|
throw new Error(`restoreKeyBackup expects Uint8Array, got ${privKey}`);
|
||||||
|
}
|
||||||
// Cache the key, if possible.
|
// Cache the key, if possible.
|
||||||
// This is async.
|
// This is async.
|
||||||
this.crypto
|
this.cryptoBackend
|
||||||
.storeSessionBackupPrivateKey(privKey)
|
.storeSessionBackupPrivateKey(privKey)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
logger.warn("Error caching session backup key:", e);
|
logger.warn("Error caching session backup key:", e);
|
||||||
@ -3849,7 +3853,7 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
algorithm.free();
|
algorithm.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.getCrypto()?.importRoomKeys(keys, {
|
await this.cryptoBackend.importRoomKeys(keys, {
|
||||||
progressCallback,
|
progressCallback,
|
||||||
untrusted,
|
untrusted,
|
||||||
source: "backup",
|
source: "backup",
|
||||||
|
@ -284,6 +284,30 @@ export interface CryptoApi {
|
|||||||
* @returns a VerificationRequest when the request has been sent to the other party.
|
* @returns a VerificationRequest when the request has been sent to the other party.
|
||||||
*/
|
*/
|
||||||
requestDeviceVerification(userId: string, deviceId: string): Promise<VerificationRequest>;
|
requestDeviceVerification(userId: string, deviceId: string): Promise<VerificationRequest>;
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Secure key backup
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the backup decryption key we have saved in our store.
|
||||||
|
*
|
||||||
|
* This can be used for gossiping the key to other devices.
|
||||||
|
*
|
||||||
|
* @returns the key, if any, or null
|
||||||
|
*/
|
||||||
|
getSessionBackupPrivateKey(): Promise<Uint8Array | null>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the backup decryption key.
|
||||||
|
*
|
||||||
|
* This should be called if the client has received the key from another device via secret sharing (gossiping).
|
||||||
|
*
|
||||||
|
* @param key - the backup decryption key
|
||||||
|
*/
|
||||||
|
storeSessionBackupPrivateKey(key: Uint8Array): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -698,6 +698,33 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
|
|||||||
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods);
|
return new RustVerificationRequest(request, this.outgoingRequestProcessor, this._supportedVerificationMethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch the backup decryption key we have saved in our store.
|
||||||
|
*
|
||||||
|
* Implementation of {@link CryptoApi#getSessionBackupPrivateKey}.
|
||||||
|
*
|
||||||
|
* @returns the key, if any, or null
|
||||||
|
*/
|
||||||
|
public async getSessionBackupPrivateKey(): Promise<Uint8Array | null> {
|
||||||
|
const backupKeys: RustSdkCryptoJs.BackupKeys = await this.olmMachine.getBackupKeys();
|
||||||
|
if (!backupKeys.decryptionKeyBase64) return null;
|
||||||
|
return Buffer.from(backupKeys.decryptionKeyBase64, "base64");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the backup decryption key.
|
||||||
|
*
|
||||||
|
* Implementation of {@link CryptoApi#storeSessionBackupPrivateKey}.
|
||||||
|
*
|
||||||
|
* @param key - the backup decryption key
|
||||||
|
*/
|
||||||
|
public async storeSessionBackupPrivateKey(key: Uint8Array): Promise<void> {
|
||||||
|
const base64Key = Buffer.from(key).toString("base64");
|
||||||
|
|
||||||
|
// TODO get version from backupManager
|
||||||
|
await this.olmMachine.saveBackupDecryptionKey(RustSdkCryptoJs.BackupDecryptionKey.fromBase64(base64Key), "");
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// SyncCryptoCallbacks implementation
|
// SyncCryptoCallbacks implementation
|
||||||
|
@ -1482,10 +1482,10 @@
|
|||||||
"@jridgewell/resolve-uri" "3.1.0"
|
"@jridgewell/resolve-uri" "3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||||
|
|
||||||
"@matrix-org/matrix-sdk-crypto-wasm@^1.0.1":
|
"@matrix-org/matrix-sdk-crypto-wasm@^1.1.0":
|
||||||
version "1.0.1"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-1.0.1.tgz#21a0557a7bb3f60b37c6d412be8906c056fe79b8"
|
resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-1.1.0.tgz#43996a2c5fc8786999eeaaf6df51007244f6b3c4"
|
||||||
integrity sha512-VTwV5IowvhhLXwAsDDAv02bC5/qBQbG2YtpYAije11253sQ3MePIoSR+dS40Ih3lAlEzqQ00GU3O+i45jMzIRQ==
|
integrity sha512-BSMYqXRgQOHG3N18z8b05x3UQcdLL3XDrxjtjjA88t9PadZ7RwNowLm1Sx3ESzdzRX+r1SEVAWs2JnTTs0rv3Q==
|
||||||
|
|
||||||
"@matrix-org/olm@https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz":
|
"@matrix-org/olm@https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz":
|
||||||
version "3.2.14"
|
version "3.2.14"
|
||||||
|
Reference in New Issue
Block a user