Skip to content

Commit

Permalink
Use new CrytoApi.restoreKeyBackup & `CrytoApi.restoreKeyBackupFromP…
Browse files Browse the repository at this point in the history
…assprhase` api
  • Loading branch information
florianduros committed Nov 7, 2024
1 parent a355292 commit 36c92ee
Showing 1 changed file with 38 additions and 42 deletions.
80 changes: 38 additions & 42 deletions src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ Please see LICENSE files in the repository root for full details.
*/

import React, { ChangeEvent } from "react";
import { MatrixClient, MatrixError, SecretStorage } from "matrix-js-sdk/src/matrix";
import { decodeRecoveryKey, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
import { IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup";
import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
import { decodeRecoveryKey, KeyBackupInfo, KeyBackupRestoreResult } from "matrix-js-sdk/src/crypto-api";
import { logger } from "matrix-js-sdk/src/logger";

import { MatrixClientPeg } from "../../../../MatrixClientPeg";
Expand Down Expand Up @@ -42,12 +41,11 @@ interface IProps {

interface IState {
backupInfo: KeyBackupInfo | null;
backupKeyStored: Record<string, SecretStorage.SecretStorageKeyDescription> | null;
loading: boolean;
loadError: boolean | null;
restoreError: unknown | null;
recoveryKey: string;
recoverInfo: IKeyBackupRestoreResult | null;
recoverInfo: KeyBackupRestoreResult | null;
recoveryKeyValid: boolean;
forceRecoveryKey: boolean;
passPhrase: string;
Expand All @@ -72,7 +70,6 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
super(props);
this.state = {
backupInfo: null,
backupKeyStored: null,
loading: false,
loadError: null,
restoreError: null,
Expand Down Expand Up @@ -137,7 +134,8 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
};

private onPassPhraseNext = async (): Promise<void> => {
if (!this.state.backupInfo) return;
const crypto = MatrixClientPeg.safeGet().getCrypto();
if (!crypto) return;
this.setState({
loading: true,
restoreError: null,
Expand All @@ -146,13 +144,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
try {
// We do still restore the key backup: we must ensure that the key backup key
// is the right one and restoring it is currently the only way we can do this.
const recoverInfo = await MatrixClientPeg.safeGet().restoreKeyBackupWithPassword(
this.state.passPhrase,
undefined,
undefined,
this.state.backupInfo,
{ progressCallback: this.progressCallback },
);
const recoverInfo = await crypto.restoreKeyBackupWithPassphrase(this.state.passPhrase, {
progressCallback: this.progressCallback,
});

if (!this.props.showSummary) {
this.props.onFinished(true);
Expand All @@ -172,21 +166,23 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
};

private onRecoveryKeyNext = async (): Promise<void> => {
if (!this.state.recoveryKeyValid || !this.state.backupInfo) return;
const crypto = MatrixClientPeg.safeGet().getCrypto();
if (!this.state.recoveryKeyValid || !this.state.backupInfo?.version || !crypto) return;

this.setState({
loading: true,
restoreError: null,
restoreType: RestoreType.RecoveryKey,
});
try {
const recoverInfo = await MatrixClientPeg.safeGet().restoreKeyBackupWithRecoveryKey(
this.state.recoveryKey,
undefined,
undefined,
this.state.backupInfo,
{ progressCallback: this.progressCallback },
await crypto.storeSessionBackupPrivateKey(
decodeRecoveryKey(this.state.recoveryKey),
this.state.backupInfo.version,
);
const recoverInfo = await crypto.restoreKeyBackup({
progressCallback: this.progressCallback,
});

if (!this.props.showSummary) {
this.props.onFinished(true);
return;
Expand All @@ -210,44 +206,41 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
});
};

private async restoreWithSecretStorage(): Promise<void> {
private async restoreWithSecretStorage(): Promise<boolean> {
const crypto = MatrixClientPeg.safeGet().getCrypto();
if (!crypto) return false;

this.setState({
loading: true,
restoreError: null,
restoreType: RestoreType.SecretStorage,
});
try {
let recoverInfo: KeyBackupRestoreResult | null = null;
// `accessSecretStorage` may prompt for storage access as needed.
await accessSecretStorage(async (): Promise<void> => {
if (!this.state.backupInfo) return;
await MatrixClientPeg.safeGet().restoreKeyBackupWithSecretStorage(
this.state.backupInfo,
undefined,
undefined,
{ progressCallback: this.progressCallback },
);
await crypto.loadSessionBackupPrivateKeyFromSecretStorage();
recoverInfo = await crypto.restoreKeyBackup({ progressCallback: this.progressCallback });
});
this.setState({
loading: false,
recoverInfo,
});
return true;
} catch (e) {
logger.log("Error restoring backup", e);
logger.log("restoreWithSecretStorage failed:", e);
this.setState({
restoreError: e,
loading: false,
});
return false;
}
}

private async restoreWithCachedKey(backupInfo: KeyBackupInfo | null): Promise<boolean> {
if (!backupInfo) return false;
const crypto = MatrixClientPeg.safeGet().getCrypto();
if (!crypto) return false;
try {
const recoverInfo = await MatrixClientPeg.safeGet().restoreKeyBackupWithCache(
undefined /* targetRoomId */,
undefined /* targetSessionId */,
backupInfo,
{ progressCallback: this.progressCallback },
);
const recoverInfo = await crypto.restoreKeyBackup({ progressCallback: this.progressCallback });
this.setState({
recoverInfo,
});
Expand All @@ -270,7 +263,6 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
const backupKeyStored = has4S ? await cli.isKeyBackupKeyStored() : null;
this.setState({
backupInfo,
backupKeyStored,
});

const gotCache = await this.restoreWithCachedKey(backupInfo);
Expand All @@ -282,9 +274,13 @@ export default class RestoreKeyBackupDialog extends React.PureComponent<IProps,
return;
}

// If the backup key is stored, we can proceed directly to restore.
if (backupKeyStored) {
return this.restoreWithSecretStorage();
const hasBackupFromSS = backupKeyStored && (await this.restoreWithSecretStorage());
if (hasBackupFromSS) {
logger.log("RestoreKeyBackupDialog: found backup key in secret storage");
this.setState({
loading: false,
});
return;
}

this.setState({
Expand Down

0 comments on commit 36c92ee

Please sign in to comment.