diff --git a/src/CrossSigningManager.js b/src/CrossSigningManager.js index f428697e74..b43af7b8b2 100644 --- a/src/CrossSigningManager.js +++ b/src/CrossSigningManager.js @@ -162,6 +162,20 @@ export const crossSigningCallbacks = { onSecretRequested, }; +export async function promptForBackupPassphrase() { + let key; + + const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog'); + const { finished } = Modal.createTrackedDialog('Restore Backup', '', RestoreKeyBackupDialog, { + showSummary: false, keyCallback: k => key = k, + }, null, /* priority = */ false, /* static = */ false); + + const success = await finished; + if (!success) throw new Error("Key backup prompt cancelled"); + + return key; +} + /** * This helper should be used whenever you need to access secret storage. It * ensures that secret storage (and also cross-signing since they each depend on @@ -218,6 +232,7 @@ export async function accessSecretStorage(func = async () => { }, force = false) throw new Error("Cross-signing key upload auth canceled"); } }, + getBackupPassphrase: promptForBackupPassphrase, }); } diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 49b103ecf7..35529fbc5b 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -23,6 +23,7 @@ import { scorePassword } from '../../../../utils/PasswordScorer'; import FileSaver from 'file-saver'; import { _t } from '../../../../languageHandler'; import Modal from '../../../../Modal'; +import { promptForBackupPassphrase } from '../../../../CrossSigningManager'; const PHASE_LOADING = 0; const PHASE_MIGRATE = 1; @@ -243,6 +244,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent { createSecretStorageKey: async () => this._keyInfo, keyBackupInfo: this.state.backupInfo, setupNewKeyBackup: !this.state.backupInfo && this.state.useKeyBackup, + getKeyBackupPassphrase: promptForBackupPassphrase, }); } this.setState({ diff --git a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js index 438806bf82..8e4a4e1e60 100644 --- a/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js +++ b/src/components/views/dialogs/keybackup/RestoreKeyBackupDialog.js @@ -36,6 +36,9 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { // if false, will close the dialog as soon as the restore completes succesfully // default: true showSummary: PropTypes.bool, + // If specified, gather the key from the user but then call the function with the backup + // key rather than actually (necessarily) restoring the backup. + keyCallback: PropTypes.func, }; static defaultProps = { @@ -103,9 +106,18 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { restoreType: RESTORE_TYPE_PASSPHRASE, }); 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.get().restoreKeyBackupWithPassword( this.state.passPhrase, undefined, undefined, this.state.backupInfo, ); + if (this.props.keyCallback) { + const key = await MatrixClientPeg.get().keyBackupKeyFromPassword( + this.state.passPhrase, this.state.backupInfo, + ); + this.props.keyCallback(key); + } + if (!this.props.showSummary) { this.props.onFinished(true); return; @@ -135,6 +147,10 @@ export default class RestoreKeyBackupDialog extends React.PureComponent { const recoverInfo = await MatrixClientPeg.get().restoreKeyBackupWithRecoveryKey( this.state.recoveryKey, undefined, undefined, this.state.backupInfo, ); + if (this.props.keyCallback) { + const key = MatrixClientPeg.get().keyBackupKeyFromRecoveryKey(this.state.recoveryKey); + this.props.keyCallback(key); + } if (!this.props.showSummary) { this.props.onFinished(true); return;