Merge pull request #5149 from matrix-org/jryans/defer-cross-signing-setup
Migrate to new, separate APIs for cross-signing and secret storagepull/21833/head
						commit
						e2acec6059
					
				| 
						 | 
				
			
			@ -69,19 +69,19 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
 | 
			
		|||
    if (keyInfoEntries.length > 1) {
 | 
			
		||||
        throw new Error("Multiple storage key requests not implemented");
 | 
			
		||||
    }
 | 
			
		||||
    const [name, info] = keyInfoEntries[0];
 | 
			
		||||
    const [keyId, keyInfo] = keyInfoEntries[0];
 | 
			
		||||
 | 
			
		||||
    // Check the in-memory cache
 | 
			
		||||
    if (isCachingAllowed() && secretStorageKeys[name]) {
 | 
			
		||||
        return [name, secretStorageKeys[name]];
 | 
			
		||||
    if (isCachingAllowed() && secretStorageKeys[keyId]) {
 | 
			
		||||
        return [keyId, secretStorageKeys[keyId]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const inputToKey = async ({ passphrase, recoveryKey }) => {
 | 
			
		||||
        if (passphrase) {
 | 
			
		||||
            return deriveKey(
 | 
			
		||||
                passphrase,
 | 
			
		||||
                info.passphrase.salt,
 | 
			
		||||
                info.passphrase.iterations,
 | 
			
		||||
                keyInfo.passphrase.salt,
 | 
			
		||||
                keyInfo.passphrase.iterations,
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            return decodeRecoveryKey(recoveryKey);
 | 
			
		||||
| 
						 | 
				
			
			@ -93,10 +93,10 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
 | 
			
		|||
        AccessSecretStorageDialog,
 | 
			
		||||
        /* props= */
 | 
			
		||||
        {
 | 
			
		||||
            keyInfo: info,
 | 
			
		||||
            keyInfo,
 | 
			
		||||
            checkPrivateKey: async (input) => {
 | 
			
		||||
                const key = await inputToKey(input);
 | 
			
		||||
                return await MatrixClientPeg.get().checkSecretStorageKey(key, info);
 | 
			
		||||
                return await MatrixClientPeg.get().checkSecretStorageKey(key, keyInfo);
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
        /* className= */ null,
 | 
			
		||||
| 
						 | 
				
			
			@ -118,11 +118,15 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
 | 
			
		|||
    const key = await inputToKey(input);
 | 
			
		||||
 | 
			
		||||
    // Save to cache to avoid future prompts in the current session
 | 
			
		||||
    if (isCachingAllowed()) {
 | 
			
		||||
        secretStorageKeys[name] = key;
 | 
			
		||||
    }
 | 
			
		||||
    cacheSecretStorageKey(keyId, key);
 | 
			
		||||
 | 
			
		||||
    return [name, key];
 | 
			
		||||
    return [keyId, key];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cacheSecretStorageKey(keyId, key) {
 | 
			
		||||
    if (isCachingAllowed()) {
 | 
			
		||||
        secretStorageKeys[keyId] = key;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const onSecretRequested = async function({
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +174,7 @@ const onSecretRequested = async function({
 | 
			
		|||
 | 
			
		||||
export const crossSigningCallbacks = {
 | 
			
		||||
    getSecretStorageKey,
 | 
			
		||||
    cacheSecretStorageKey,
 | 
			
		||||
    onSecretRequested,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +223,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
 | 
			
		|||
            const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
 | 
			
		||||
                import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
 | 
			
		||||
                {
 | 
			
		||||
                    force: forceReset,
 | 
			
		||||
                    forceReset,
 | 
			
		||||
                },
 | 
			
		||||
                null,
 | 
			
		||||
                /* priority = */ false,
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +244,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
 | 
			
		|||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
 | 
			
		||||
            await cli.bootstrapSecretStorage({
 | 
			
		||||
            await cli.bootstrapCrossSigning({
 | 
			
		||||
                authUploadDeviceSigningKeys: async (makeRequest) => {
 | 
			
		||||
                    const { finished } = Modal.createTrackedDialog(
 | 
			
		||||
                        'Cross-signing keys dialog', '', InteractiveAuthDialog,
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +259,9 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
 | 
			
		|||
                        throw new Error("Cross-signing key upload auth canceled");
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                getBackupPassphrase: promptForBackupPassphrase,
 | 
			
		||||
            });
 | 
			
		||||
            await cli.bootstrapSecretStorage({
 | 
			
		||||
                getKeyBackupPassphrase: promptForBackupPassphrase,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -207,9 +207,13 @@ export default class DeviceListener {
 | 
			
		|||
        // (we add a listener on sync to do once check after the initial sync is done)
 | 
			
		||||
        if (!cli.isInitialSyncComplete()) return;
 | 
			
		||||
 | 
			
		||||
        // JRS: This will change again in the next PR which moves secret storage
 | 
			
		||||
        // later in the process.
 | 
			
		||||
        const crossSigningReady = await cli.isCrossSigningReady();
 | 
			
		||||
        const secretStorageReady = await cli.isSecretStorageReady();
 | 
			
		||||
        const allSystemsReady = crossSigningReady && secretStorageReady;
 | 
			
		||||
 | 
			
		||||
        if (this.dismissedThisDeviceToast || crossSigningReady) {
 | 
			
		||||
        if (this.dismissedThisDeviceToast || allSystemsReady) {
 | 
			
		||||
            hideSetupEncryptionToast();
 | 
			
		||||
        } else if (this.shouldShowSetupEncryptionToast()) {
 | 
			
		||||
            // make sure our keys are finished downloading
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,12 +56,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
 | 
			
		|||
    static propTypes = {
 | 
			
		||||
        hasCancel: PropTypes.bool,
 | 
			
		||||
        accountPassword: PropTypes.string,
 | 
			
		||||
        force: PropTypes.bool,
 | 
			
		||||
        forceReset: PropTypes.bool,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static defaultProps = {
 | 
			
		||||
        hasCancel: true,
 | 
			
		||||
        force: false,
 | 
			
		||||
        forceReset: false,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    constructor(props) {
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +118,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
 | 
			
		|||
                MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const { force } = this.props;
 | 
			
		||||
            const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE;
 | 
			
		||||
            const { forceReset } = this.props;
 | 
			
		||||
            const phase = (backupInfo && !forceReset) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE;
 | 
			
		||||
 | 
			
		||||
            this.setState({
 | 
			
		||||
                phase,
 | 
			
		||||
| 
						 | 
				
			
			@ -277,20 +277,25 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
 | 
			
		|||
 | 
			
		||||
        const cli = MatrixClientPeg.get();
 | 
			
		||||
 | 
			
		||||
        const { force } = this.props;
 | 
			
		||||
        const { forceReset } = this.props;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if (force) {
 | 
			
		||||
                console.log("Forcing secret storage reset"); // log something so we can debug this later
 | 
			
		||||
            if (forceReset) {
 | 
			
		||||
                console.log("Forcing cross-signing and secret storage reset");
 | 
			
		||||
                await cli.bootstrapSecretStorage({
 | 
			
		||||
                    authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
 | 
			
		||||
                    createSecretStorageKey: async () => this._recoveryKey,
 | 
			
		||||
                    setupNewKeyBackup: true,
 | 
			
		||||
                    setupNewSecretStorage: true,
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
                await cli.bootstrapSecretStorage({
 | 
			
		||||
                await cli.bootstrapCrossSigning({
 | 
			
		||||
                    authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
 | 
			
		||||
                    setupNewCrossSigning: true,
 | 
			
		||||
                });
 | 
			
		||||
            } else {
 | 
			
		||||
                await cli.bootstrapCrossSigning({
 | 
			
		||||
                    authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
 | 
			
		||||
                });
 | 
			
		||||
                await cli.bootstrapSecretStorage({
 | 
			
		||||
                    createSecretStorageKey: async () => this._recoveryKey,
 | 
			
		||||
                    keyBackupInfo: this.state.backupInfo,
 | 
			
		||||
                    setupNewKeyBackup: !this.state.backupInfo,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,6 +89,7 @@ export default class CrossSigningPanel extends React.PureComponent {
 | 
			
		|||
        const homeserverSupportsCrossSigning =
 | 
			
		||||
            await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing");
 | 
			
		||||
        const crossSigningReady = await cli.isCrossSigningReady();
 | 
			
		||||
        const secretStorageReady = await cli.isSecretStorageReady();
 | 
			
		||||
 | 
			
		||||
        this.setState({
 | 
			
		||||
            crossSigningPublicKeysOnDevice,
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +102,7 @@ export default class CrossSigningPanel extends React.PureComponent {
 | 
			
		|||
            secretStorageKeyInAccount,
 | 
			
		||||
            homeserverSupportsCrossSigning,
 | 
			
		||||
            crossSigningReady,
 | 
			
		||||
            secretStorageReady,
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -151,6 +153,7 @@ export default class CrossSigningPanel extends React.PureComponent {
 | 
			
		|||
            secretStorageKeyInAccount,
 | 
			
		||||
            homeserverSupportsCrossSigning,
 | 
			
		||||
            crossSigningReady,
 | 
			
		||||
            secretStorageReady,
 | 
			
		||||
        } = this.state;
 | 
			
		||||
 | 
			
		||||
        let errorSection;
 | 
			
		||||
| 
						 | 
				
			
			@ -166,14 +169,19 @@ export default class CrossSigningPanel extends React.PureComponent {
 | 
			
		|||
            summarisedStatus = <p>{_t(
 | 
			
		||||
                "Your homeserver does not support cross-signing.",
 | 
			
		||||
            )}</p>;
 | 
			
		||||
        } else if (crossSigningReady) {
 | 
			
		||||
        } else if (crossSigningReady && secretStorageReady) {
 | 
			
		||||
            summarisedStatus = <p>✅ {_t(
 | 
			
		||||
                "Cross-signing and secret storage are enabled.",
 | 
			
		||||
                "Cross-signing and secret storage are ready for use.",
 | 
			
		||||
            )}</p>;
 | 
			
		||||
        } else if (crossSigningReady && !secretStorageReady) {
 | 
			
		||||
            summarisedStatus = <p>✅ {_t(
 | 
			
		||||
                "Cross-signing is ready for use, but secret storage is " +
 | 
			
		||||
                "currently not being used to backup your keys.",
 | 
			
		||||
            )}</p>;
 | 
			
		||||
        } else if (crossSigningPrivateKeysInStorage) {
 | 
			
		||||
            summarisedStatus = <p>{_t(
 | 
			
		||||
                "Your account has a cross-signing identity in secret storage, but it " +
 | 
			
		||||
                "is not yet trusted by this session.",
 | 
			
		||||
                "Your account has a cross-signing identity in secret storage, " +
 | 
			
		||||
                "but it is not yet trusted by this session.",
 | 
			
		||||
            )}</p>;
 | 
			
		||||
        } else {
 | 
			
		||||
            summarisedStatus = <p>{_t(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -645,7 +645,8 @@
 | 
			
		|||
    "Confirm password": "Confirm password",
 | 
			
		||||
    "Change Password": "Change Password",
 | 
			
		||||
    "Your homeserver does not support cross-signing.": "Your homeserver does not support cross-signing.",
 | 
			
		||||
    "Cross-signing and secret storage are enabled.": "Cross-signing and secret storage are enabled.",
 | 
			
		||||
    "Cross-signing and secret storage are ready for use.": "Cross-signing and secret storage are ready for use.",
 | 
			
		||||
    "Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.": "Cross-signing is ready for use, but secret storage is currently not being used to backup your keys.",
 | 
			
		||||
    "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.": "Your account has a cross-signing identity in secret storage, but it is not yet trusted by this session.",
 | 
			
		||||
    "Cross-signing and secret storage are not yet set up.": "Cross-signing and secret storage are not yet set up.",
 | 
			
		||||
    "Reset cross-signing and secret storage": "Reset cross-signing and secret storage",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,6 +115,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
 | 
			
		|||
            body.append("cross_signing_supported_by_hs",
 | 
			
		||||
                String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")));
 | 
			
		||||
            body.append("cross_signing_ready", String(await client.isCrossSigningReady()));
 | 
			
		||||
            body.append("secret_storage_ready", String(await client.isSecretStorageReady()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue