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

Implement key backup APIs for rust and create backup in bootstrapSecretStorage (#3690)

* new resetKeyBackup API

* add delete backup version test

* code review

* support backup creation in rust

* code review
This commit is contained in:
Valere
2023-09-05 15:52:49 +02:00
committed by GitHub
parent 989c5a3dda
commit d7831f9e5b
3 changed files with 185 additions and 45 deletions

View File

@@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import anotherjson from "another-json";
import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto";
@@ -63,9 +64,15 @@ import { RustBackupCryptoEventMap, RustBackupCryptoEvents, RustBackupManager } f
import { TypedReEmitter } from "../ReEmitter";
import { randomString } from "../randomstring";
import { ClientStoppedError } from "../errors";
import { ISignatures } from "../@types/signed";
const ALL_VERIFICATION_METHODS = ["m.sas.v1", "m.qr_code.scan.v1", "m.qr_code.show.v1", "m.reciprocate.v1"];
interface ISignableObject {
signatures?: ISignatures;
unsigned?: object;
}
/**
* An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto.
*
@@ -555,6 +562,7 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
public async bootstrapSecretStorage({
createSecretStorageKey,
setupNewSecretStorage,
setupNewKeyBackup,
}: CreateSecretStorageOpts = {}): Promise<void> {
// If an AES Key is already stored in the secret storage and setupNewSecretStorage is not set
// we don't want to create a new key
@@ -598,6 +606,10 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
await this.secretStorage.store("m.cross_signing.master", crossSigningPrivateKeys.masterKey);
await this.secretStorage.store("m.cross_signing.user_signing", crossSigningPrivateKeys.userSigningKey);
await this.secretStorage.store("m.cross_signing.self_signing", crossSigningPrivateKeys.self_signing_key);
if (setupNewKeyBackup) {
await this.resetKeyBackup();
}
}
}
@@ -938,18 +950,53 @@ export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, RustCryptoEv
return await this.backupManager.checkKeyBackupAndEnable(true);
}
/**
* Implementation of {@link CryptoApi#resetKeyBackup}.
*/
public async resetKeyBackup(): Promise<void> {
// stub
}
/**
* Implementation of {@link CryptoApi#deleteKeyBackupVersion}.
*/
public async deleteKeyBackupVersion(version: string): Promise<void> {
// stub
await this.backupManager.deleteKeyBackupVersion(version);
}
/**
* Implementation of {@link CryptoApi#resetKeyBackup}.
*/
public async resetKeyBackup(): Promise<void> {
const backupInfo = await this.backupManager.setupKeyBackup((o) => this.signObject(o));
// we want to store the private key in 4S
// need to check if 4S is set up?
if (await this.secretStorageHasAESKey()) {
await this.secretStorage.store("m.megolm_backup.v1", backupInfo.decryptionKey.toBase64());
}
// we can check and start async
this.checkKeyBackupAndEnable();
}
/**
* 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}.
*
* @param obj - The object to sign
*/
private async signObject<T extends ISignableObject & object>(obj: T): Promise<void> {
const sigs = new Map(Object.entries(obj.signatures || {}));
const unsigned = obj.unsigned;
delete obj.signatures;
delete obj.unsigned;
const userSignatures = sigs.get(this.userId) || {};
const canonalizedJson = anotherjson.stringify(obj);
const signatures: RustSdkCryptoJs.Signatures = await this.olmMachine.sign(canonalizedJson);
const map = JSON.parse(signatures.asJSON());
sigs.set(this.userId, { ...userSignatures, ...map[this.userId] });
if (unsigned !== undefined) obj.unsigned = unsigned;
obj.signatures = Object.fromEntries(sigs.entries());
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////