Merge pull request #5149 from matrix-org/jryans/defer-cross-signing-setup

Migrate to new, separate APIs for cross-signing and secret storage
This commit is contained in:
J. Ryan Stinnett 2020-08-28 12:40:35 +01:00 committed by GitHub
commit e2acec6059
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 30 deletions

View file

@ -69,19 +69,19 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
if (keyInfoEntries.length > 1) { if (keyInfoEntries.length > 1) {
throw new Error("Multiple storage key requests not implemented"); throw new Error("Multiple storage key requests not implemented");
} }
const [name, info] = keyInfoEntries[0]; const [keyId, keyInfo] = keyInfoEntries[0];
// Check the in-memory cache // Check the in-memory cache
if (isCachingAllowed() && secretStorageKeys[name]) { if (isCachingAllowed() && secretStorageKeys[keyId]) {
return [name, secretStorageKeys[name]]; return [keyId, secretStorageKeys[keyId]];
} }
const inputToKey = async ({ passphrase, recoveryKey }) => { const inputToKey = async ({ passphrase, recoveryKey }) => {
if (passphrase) { if (passphrase) {
return deriveKey( return deriveKey(
passphrase, passphrase,
info.passphrase.salt, keyInfo.passphrase.salt,
info.passphrase.iterations, keyInfo.passphrase.iterations,
); );
} else { } else {
return decodeRecoveryKey(recoveryKey); return decodeRecoveryKey(recoveryKey);
@ -93,10 +93,10 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
AccessSecretStorageDialog, AccessSecretStorageDialog,
/* props= */ /* props= */
{ {
keyInfo: info, keyInfo,
checkPrivateKey: async (input) => { checkPrivateKey: async (input) => {
const key = await inputToKey(input); const key = await inputToKey(input);
return await MatrixClientPeg.get().checkSecretStorageKey(key, info); return await MatrixClientPeg.get().checkSecretStorageKey(key, keyInfo);
}, },
}, },
/* className= */ null, /* className= */ null,
@ -118,11 +118,15 @@ async function getSecretStorageKey({ keys: keyInfos }, ssssItemName) {
const key = await inputToKey(input); const key = await inputToKey(input);
// Save to cache to avoid future prompts in the current session // Save to cache to avoid future prompts in the current session
if (isCachingAllowed()) { cacheSecretStorageKey(keyId, key);
secretStorageKeys[name] = key;
}
return [name, key]; return [keyId, key];
}
function cacheSecretStorageKey(keyId, key) {
if (isCachingAllowed()) {
secretStorageKeys[keyId] = key;
}
} }
const onSecretRequested = async function({ const onSecretRequested = async function({
@ -170,6 +174,7 @@ const onSecretRequested = async function({
export const crossSigningCallbacks = { export const crossSigningCallbacks = {
getSecretStorageKey, getSecretStorageKey,
cacheSecretStorageKey,
onSecretRequested, onSecretRequested,
}; };
@ -218,7 +223,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '', const { finished } = Modal.createTrackedDialogAsync('Create Secret Storage dialog', '',
import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"), import("./async-components/views/dialogs/secretstorage/CreateSecretStorageDialog"),
{ {
force: forceReset, forceReset,
}, },
null, null,
/* priority = */ false, /* priority = */ false,
@ -239,7 +244,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f
} }
} else { } else {
const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog"); const InteractiveAuthDialog = sdk.getComponent("dialogs.InteractiveAuthDialog");
await cli.bootstrapSecretStorage({ await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: async (makeRequest) => { authUploadDeviceSigningKeys: async (makeRequest) => {
const { finished } = Modal.createTrackedDialog( const { finished } = Modal.createTrackedDialog(
'Cross-signing keys dialog', '', InteractiveAuthDialog, '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"); throw new Error("Cross-signing key upload auth canceled");
} }
}, },
getBackupPassphrase: promptForBackupPassphrase, });
await cli.bootstrapSecretStorage({
getKeyBackupPassphrase: promptForBackupPassphrase,
}); });
} }

View file

@ -207,9 +207,13 @@ export default class DeviceListener {
// (we add a listener on sync to do once check after the initial sync is done) // (we add a listener on sync to do once check after the initial sync is done)
if (!cli.isInitialSyncComplete()) return; 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 crossSigningReady = await cli.isCrossSigningReady();
const secretStorageReady = await cli.isSecretStorageReady();
const allSystemsReady = crossSigningReady && secretStorageReady;
if (this.dismissedThisDeviceToast || crossSigningReady) { if (this.dismissedThisDeviceToast || allSystemsReady) {
hideSetupEncryptionToast(); hideSetupEncryptionToast();
} else if (this.shouldShowSetupEncryptionToast()) { } else if (this.shouldShowSetupEncryptionToast()) {
// make sure our keys are finished downloading // make sure our keys are finished downloading

View file

@ -56,12 +56,12 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
static propTypes = { static propTypes = {
hasCancel: PropTypes.bool, hasCancel: PropTypes.bool,
accountPassword: PropTypes.string, accountPassword: PropTypes.string,
force: PropTypes.bool, forceReset: PropTypes.bool,
}; };
static defaultProps = { static defaultProps = {
hasCancel: true, hasCancel: true,
force: false, forceReset: false,
}; };
constructor(props) { constructor(props) {
@ -118,8 +118,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo) MatrixClientPeg.get().isCryptoEnabled() && await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo)
); );
const { force } = this.props; const { forceReset } = this.props;
const phase = (backupInfo && !force) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE; const phase = (backupInfo && !forceReset) ? PHASE_MIGRATE : PHASE_CHOOSE_KEY_PASSPHRASE;
this.setState({ this.setState({
phase, phase,
@ -277,20 +277,25 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.get();
const { force } = this.props; const { forceReset } = this.props;
try { try {
if (force) { if (forceReset) {
console.log("Forcing secret storage reset"); // log something so we can debug this later console.log("Forcing cross-signing and secret storage reset");
await cli.bootstrapSecretStorage({ await cli.bootstrapSecretStorage({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
createSecretStorageKey: async () => this._recoveryKey, createSecretStorageKey: async () => this._recoveryKey,
setupNewKeyBackup: true, setupNewKeyBackup: true,
setupNewSecretStorage: true, setupNewSecretStorage: true,
}); });
} else { await cli.bootstrapCrossSigning({
await cli.bootstrapSecretStorage({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth, authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
setupNewCrossSigning: true,
});
} else {
await cli.bootstrapCrossSigning({
authUploadDeviceSigningKeys: this._doBootstrapUIAuth,
});
await cli.bootstrapSecretStorage({
createSecretStorageKey: async () => this._recoveryKey, createSecretStorageKey: async () => this._recoveryKey,
keyBackupInfo: this.state.backupInfo, keyBackupInfo: this.state.backupInfo,
setupNewKeyBackup: !this.state.backupInfo, setupNewKeyBackup: !this.state.backupInfo,

View file

@ -89,6 +89,7 @@ export default class CrossSigningPanel extends React.PureComponent {
const homeserverSupportsCrossSigning = const homeserverSupportsCrossSigning =
await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"); await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing");
const crossSigningReady = await cli.isCrossSigningReady(); const crossSigningReady = await cli.isCrossSigningReady();
const secretStorageReady = await cli.isSecretStorageReady();
this.setState({ this.setState({
crossSigningPublicKeysOnDevice, crossSigningPublicKeysOnDevice,
@ -101,6 +102,7 @@ export default class CrossSigningPanel extends React.PureComponent {
secretStorageKeyInAccount, secretStorageKeyInAccount,
homeserverSupportsCrossSigning, homeserverSupportsCrossSigning,
crossSigningReady, crossSigningReady,
secretStorageReady,
}); });
} }
@ -151,6 +153,7 @@ export default class CrossSigningPanel extends React.PureComponent {
secretStorageKeyInAccount, secretStorageKeyInAccount,
homeserverSupportsCrossSigning, homeserverSupportsCrossSigning,
crossSigningReady, crossSigningReady,
secretStorageReady,
} = this.state; } = this.state;
let errorSection; let errorSection;
@ -166,14 +169,19 @@ export default class CrossSigningPanel extends React.PureComponent {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(
"Your homeserver does not support cross-signing.", "Your homeserver does not support cross-signing.",
)}</p>; )}</p>;
} else if (crossSigningReady) { } else if (crossSigningReady && secretStorageReady) {
summarisedStatus = <p> {_t( 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>; )}</p>;
} else if (crossSigningPrivateKeysInStorage) { } else if (crossSigningPrivateKeysInStorage) {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(
"Your account has a cross-signing identity in secret storage, but it " + "Your account has a cross-signing identity in secret storage, " +
"is not yet trusted by this session.", "but it is not yet trusted by this session.",
)}</p>; )}</p>;
} else { } else {
summarisedStatus = <p>{_t( summarisedStatus = <p>{_t(

View file

@ -645,7 +645,8 @@
"Confirm password": "Confirm password", "Confirm password": "Confirm password",
"Change Password": "Change Password", "Change Password": "Change Password",
"Your homeserver does not support cross-signing.": "Your homeserver does not support cross-signing.", "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.", "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.", "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", "Reset cross-signing and secret storage": "Reset cross-signing and secret storage",

View file

@ -115,6 +115,7 @@ async function collectBugReport(opts: IOpts = {}, gzipLogs = true) {
body.append("cross_signing_supported_by_hs", body.append("cross_signing_supported_by_hs",
String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"))); String(await client.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing")));
body.append("cross_signing_ready", String(await client.isCrossSigningReady())); body.append("cross_signing_ready", String(await client.isCrossSigningReady()));
body.append("secret_storage_ready", String(await client.isSecretStorageReady()));
} }
} }