diff --git a/res/css/_components.scss b/res/css/_components.scss index 27ec1088c3..54e7436886 100644 --- a/res/css/_components.scss +++ b/res/css/_components.scss @@ -202,10 +202,10 @@ @import "./views/settings/_E2eAdvancedPanel.scss"; @import "./views/settings/_EmailAddresses.scss"; @import "./views/settings/_IntegrationManager.scss"; -@import "./views/settings/_KeyBackupPanel.scss"; @import "./views/settings/_Notifications.scss"; @import "./views/settings/_PhoneNumbers.scss"; @import "./views/settings/_ProfileSettings.scss"; +@import "./views/settings/_SecureBackupPanel.scss"; @import "./views/settings/_SetIdServer.scss"; @import "./views/settings/_SetIntegrationManager.scss"; @import "./views/settings/_UpdateCheckButton.scss"; diff --git a/res/css/views/settings/_KeyBackupPanel.scss b/res/css/views/settings/_SecureBackupPanel.scss similarity index 52% rename from res/css/views/settings/_KeyBackupPanel.scss rename to res/css/views/settings/_SecureBackupPanel.scss index 872162caad..a9dab06b57 100644 --- a/res/css/views/settings/_KeyBackupPanel.scss +++ b/res/css/views/settings/_SecureBackupPanel.scss @@ -1,6 +1,6 @@ /* Copyright 2018 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 2020 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,23 +15,39 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_KeyBackupPanel_sigValid, .mx_KeyBackupPanel_sigInvalid, -.mx_KeyBackupPanel_deviceVerified, .mx_KeyBackupPanel_deviceNotVerified { +.mx_SecureBackupPanel_sigValid, .mx_SecureBackupPanel_sigInvalid, +.mx_SecureBackupPanel_deviceVerified, .mx_SecureBackupPanel_deviceNotVerified { font-weight: bold; } -.mx_KeyBackupPanel_sigValid, .mx_KeyBackupPanel_deviceVerified { +.mx_SecureBackupPanel_sigValid, .mx_SecureBackupPanel_deviceVerified { color: $e2e-verified-color; } -.mx_KeyBackupPanel_sigInvalid, .mx_KeyBackupPanel_deviceNotVerified { +.mx_SecureBackupPanel_sigInvalid, .mx_SecureBackupPanel_deviceNotVerified { color: $e2e-warning-color; } -.mx_KeyBackupPanel_deviceName { +.mx_SecureBackupPanel_deviceName { font-style: italic; } -.mx_KeyBackupPanel_buttonRow { +.mx_SecureBackupPanel_buttonRow { margin: 1em 0; + + :nth-child(n + 1) { + margin-inline-end: 10px; + } +} + +.mx_SecureBackupPanel_statusList { + border-spacing: 0; + + td { + padding: 0; + + &:first-of-type { + padding-inline-end: 1em; + } + } } diff --git a/res/css/views/settings/tabs/_SettingsTab.scss b/res/css/views/settings/tabs/_SettingsTab.scss index 5f00ed86f7..892f5fe744 100644 --- a/res/css/views/settings/tabs/_SettingsTab.scss +++ b/res/css/views/settings/tabs/_SettingsTab.scss @@ -14,6 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ +.mx_SettingsTab { + color: $muted-fg-color; +} + .mx_SettingsTab_warningText { color: $warning-color; } diff --git a/src/SecurityManager.js b/src/SecurityManager.js index 891f43b705..cc7db3ead7 100644 --- a/src/SecurityManager.js +++ b/src/SecurityManager.js @@ -250,7 +250,7 @@ export async function accessSecretStorage(func = async () => { }, forceReset = f 'Cross-signing keys dialog', '', InteractiveAuthDialog, { title: _t("Setting up keys"), - matrixClient: MatrixClientPeg.get(), + matrixClient: cli, makeRequest, }, ); diff --git a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js index 07ff3c9b76..d4b1a73c3e 100644 --- a/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js +++ b/src/async-components/views/dialogs/secretstorage/CreateSecretStorageDialog.js @@ -280,6 +280,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent { const { forceReset } = this.props; try { + // JRS: In an upcoming change, the cross-signing steps will be + // removed from here and this will instead be about secret storage + // only. if (forceReset) { console.log("Forcing cross-signing and secret storage reset"); await cli.bootstrapSecretStorage({ diff --git a/src/components/views/settings/CrossSigningPanel.js b/src/components/views/settings/CrossSigningPanel.js index 3eeb072e2d..a0ca84645f 100644 --- a/src/components/views/settings/CrossSigningPanel.js +++ b/src/components/views/settings/CrossSigningPanel.js @@ -19,9 +19,9 @@ import React from 'react'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; -import { accessSecretStorage } from '../../../SecurityManager'; import Modal from '../../../Modal'; import Spinner from '../elements/Spinner'; +import InteractiveAuthDialog from '../dialogs/InteractiveAuthDialog'; export default class CrossSigningPanel extends React.PureComponent { constructor(props) { @@ -31,13 +31,13 @@ export default class CrossSigningPanel extends React.PureComponent { this.state = { error: null, - crossSigningPublicKeysOnDevice: false, - crossSigningPrivateKeysInStorage: false, - masterPrivateKeyCached: false, - selfSigningPrivateKeyCached: false, - userSigningPrivateKeyCached: false, - sessionBackupKeyCached: false, - secretStorageKeyInAccount: false, + crossSigningPublicKeysOnDevice: null, + crossSigningPrivateKeysInStorage: null, + masterPrivateKeyCached: null, + selfSigningPrivateKeyCached: null, + userSigningPrivateKeyCached: null, + homeserverSupportsCrossSigning: null, + crossSigningReady: null, }; } @@ -66,7 +66,7 @@ export default class CrossSigningPanel extends React.PureComponent { }; _onBootstrapClick = () => { - this._bootstrapSecureSecretStorage(false); + this._bootstrapCrossSigning({ forceReset: false }); }; onStatusChanged = () => { @@ -83,14 +83,9 @@ export default class CrossSigningPanel extends React.PureComponent { const masterPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("master")); const selfSigningPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("self_signing")); const userSigningPrivateKeyCached = !!(pkCache && await pkCache.getCrossSigningKeyCache("user_signing")); - const sessionBackupKeyFromCache = await cli._crypto.getSessionBackupPrivateKey(); - const sessionBackupKeyCached = !!(sessionBackupKeyFromCache); - const sessionBackupKeyWellFormed = sessionBackupKeyFromCache instanceof Uint8Array; - const secretStorageKeyInAccount = await secretStorage.hasKey(); const homeserverSupportsCrossSigning = await cli.doesServerSupportUnstableFeature("org.matrix.e2e_cross_signing"); const crossSigningReady = await cli.isCrossSigningReady(); - const secretStorageReady = await cli.isSecretStorageReady(); this.setState({ crossSigningPublicKeysOnDevice, @@ -98,45 +93,56 @@ export default class CrossSigningPanel extends React.PureComponent { masterPrivateKeyCached, selfSigningPrivateKeyCached, userSigningPrivateKeyCached, - sessionBackupKeyCached, - sessionBackupKeyWellFormed, - secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, - secretStorageReady, }); } /** - * Bootstrapping secret storage may take one of these paths: - * 1. Create secret storage from a passphrase and store cross-signing keys - * in secret storage. + * Bootstrapping cross-signing take one of these paths: + * 1. Create cross-signing keys locally and store in secret storage (if it + * already exists on the account). * 2. Access existing secret storage by requesting passphrase and accessing * cross-signing keys as needed. * 3. All keys are loaded and there's nothing to do. * @param {bool} [forceReset] Bootstrap again even if keys already present */ - _bootstrapSecureSecretStorage = async (forceReset=false) => { + _bootstrapCrossSigning = async ({ forceReset = false }) => { this.setState({ error: null }); try { - await accessSecretStorage(() => undefined, forceReset); + const cli = MatrixClientPeg.get(); + await cli.bootstrapCrossSigning({ + authUploadDeviceSigningKeys: async (makeRequest) => { + const { finished } = Modal.createTrackedDialog( + 'Cross-signing keys dialog', '', InteractiveAuthDialog, + { + title: _t("Setting up keys"), + matrixClient: cli, + makeRequest, + }, + ); + const [confirmed] = await finished; + if (!confirmed) { + throw new Error("Cross-signing key upload auth canceled"); + } + }, + setupNewCrossSigning: forceReset, + }); } catch (e) { this.setState({ error: e }); - console.error("Error bootstrapping secret storage", e); + console.error("Error bootstrapping cross-signing", e); } if (this._unmounted) return; this._getUpdatedStatus(); } - onDestroyStorage = (act) => { - if (!act) return; - this._bootstrapSecureSecretStorage(true); - } - - _destroySecureSecretStorage = () => { + _resetCrossSigning = () => { const ConfirmDestroyCrossSigningDialog = sdk.getComponent("dialogs.ConfirmDestroyCrossSigningDialog"); Modal.createDialog(ConfirmDestroyCrossSigningDialog, { - onFinished: this.onDestroyStorage, + onFinished: (act) => { + if (!act) return; + this._bootstrapCrossSigning({ forceReset: true }); + }, }); } @@ -149,12 +155,8 @@ export default class CrossSigningPanel extends React.PureComponent { masterPrivateKeyCached, selfSigningPrivateKeyCached, userSigningPrivateKeyCached, - sessionBackupKeyCached, - sessionBackupKeyWellFormed, - secretStorageKeyInAccount, homeserverSupportsCrossSigning, crossSigningReady, - secretStorageReady, } = this.state; let errorSection; @@ -169,14 +171,9 @@ export default class CrossSigningPanel extends React.PureComponent { summarisedStatus =

{_t( "Your homeserver does not support cross-signing.", )}

; - } else if (crossSigningReady && secretStorageReady) { + } else if (crossSigningReady) { summarisedStatus =

✅ {_t( - "Cross-signing and secret storage are ready for use.", - )}

; - } else if (crossSigningReady && !secretStorageReady) { - summarisedStatus =

✅ {_t( - "Cross-signing is ready for use, but secret storage is " + - "currently not being used to backup your keys.", + "Cross-signing is ready for use.", )}

; } else if (crossSigningPrivateKeysInStorage) { summarisedStatus =

{_t( @@ -185,17 +182,15 @@ export default class CrossSigningPanel extends React.PureComponent { )}

; } else { summarisedStatus =

{_t( - "Cross-signing and secret storage are not yet set up.", + "Cross-signing is not set up.", )}

; } const keysExistAnywhere = ( - secretStorageKeyInAccount || crossSigningPrivateKeysInStorage || crossSigningPublicKeysOnDevice ); const keysExistEverywhere = ( - secretStorageKeyInAccount && crossSigningPrivateKeysInStorage && crossSigningPublicKeysOnDevice ); @@ -204,8 +199,8 @@ export default class CrossSigningPanel extends React.PureComponent { if (keysExistAnywhere) { resetButton = (
- - {_t("Reset cross-signing and secret storage")} + + {_t("Reset")}
); @@ -217,22 +212,12 @@ export default class CrossSigningPanel extends React.PureComponent { bootstrapButton = (
- {_t("Bootstrap cross-signing and secret storage")} + {_t("Set up")}
); } - let sessionBackupKeyWellFormedText = ""; - if (sessionBackupKeyCached) { - sessionBackupKeyWellFormedText = ", "; - if (sessionBackupKeyWellFormed) { - sessionBackupKeyWellFormedText += _t("well formed"); - } else { - sessionBackupKeyWellFormedText += _t("unexpected type"); - } - } - return (
{summarisedStatus} @@ -259,17 +244,6 @@ export default class CrossSigningPanel extends React.PureComponent { {_t("User signing private key:")} {userSigningPrivateKeyCached ? _t("cached locally") : _t("not found locally")} - - {_t("Session backup key:")} - - {sessionBackupKeyCached ? _t("cached locally") : _t("not found locally")} - {sessionBackupKeyWellFormedText} - - - - {_t("Secret storage public key:")} - {secretStorageKeyInAccount ? _t("in account data") : _t("not found")} - {_t("Homeserver feature support:")} {homeserverSupportsCrossSigning ? _t("exists") : _t("not found")} diff --git a/src/components/views/settings/KeyBackupPanel.js b/src/components/views/settings/SecureBackupPanel.js similarity index 60% rename from src/components/views/settings/KeyBackupPanel.js rename to src/components/views/settings/SecureBackupPanel.js index 8a74276f58..7f0655d54a 100644 --- a/src/components/views/settings/KeyBackupPanel.js +++ b/src/components/views/settings/SecureBackupPanel.js @@ -17,13 +17,17 @@ limitations under the License. import React from 'react'; -import * as sdk from '../../../index'; import {MatrixClientPeg} from '../../../MatrixClientPeg'; import { _t } from '../../../languageHandler'; import Modal from '../../../Modal'; import { isSecureBackupRequired } from '../../../utils/WellKnownUtils'; +import Spinner from '../elements/Spinner'; +import AccessibleButton from '../elements/AccessibleButton'; +import QuestionDialog from '../dialogs/QuestionDialog'; +import RestoreKeyBackupDialog from '../dialogs/keybackup/RestoreKeyBackupDialog'; +import { accessSecretStorage } from '../../../SecurityManager'; -export default class KeyBackupPanel extends React.PureComponent { +export default class SecureBackupPanel extends React.PureComponent { constructor(props) { super(props); @@ -31,9 +35,13 @@ export default class KeyBackupPanel extends React.PureComponent { this.state = { loading: true, error: null, + backupKeyStored: null, + backupKeyCached: null, + backupKeyWellFormed: null, + secretStorageKeyInAccount: null, + secretStorageReady: null, backupInfo: null, backupSigStatus: null, - backupKeyStored: null, sessionsRemaining: 0, }; } @@ -73,56 +81,73 @@ export default class KeyBackupPanel extends React.PureComponent { } async _checkKeyBackupStatus() { + this._getUpdatedDiagnostics(); try { const {backupInfo, trustInfo} = await MatrixClientPeg.get().checkKeyBackup(); - const backupKeyStored = Boolean(await MatrixClientPeg.get().isKeyBackupKeyStored()); this.setState({ + loading: false, + error: null, backupInfo, backupSigStatus: trustInfo, - backupKeyStored, - error: null, - loading: false, }); } catch (e) { console.log("Unable to fetch check backup status", e); if (this._unmounted) return; this.setState({ + loading: false, error: e, backupInfo: null, backupSigStatus: null, - backupKeyStored: null, - loading: false, }); } } async _loadBackupStatus() { - this.setState({loading: true}); + this.setState({ loading: true }); + this._getUpdatedDiagnostics(); try { const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo); - const backupKeyStored = await MatrixClientPeg.get().isKeyBackupKeyStored(); if (this._unmounted) return; this.setState({ + loading: false, error: null, backupInfo, backupSigStatus, - backupKeyStored, - loading: false, }); } catch (e) { console.log("Unable to fetch key backup status", e); if (this._unmounted) return; this.setState({ + loading: false, error: e, backupInfo: null, backupSigStatus: null, - backupKeyStored: null, - loading: false, }); } } + async _getUpdatedDiagnostics() { + const cli = MatrixClientPeg.get(); + const secretStorage = cli._crypto._secretStorage; + + const backupKeyStored = await cli.isKeyBackupKeyStored(); + const backupKeyFromCache = await cli._crypto.getSessionBackupPrivateKey(); + const backupKeyCached = !!(backupKeyFromCache); + const backupKeyWellFormed = backupKeyFromCache instanceof Uint8Array; + const secretStorageKeyInAccount = await secretStorage.hasKey(); + const secretStorageReady = await cli.isSecretStorageReady(); + + if (this._unmounted) return; + this.setState({ + backupKeyStored, + backupKeyCached, + backupKeyWellFormed, + secretStorageKeyInAccount, + secretStorageReady, + }); + } + _startNewBackup = () => { Modal.createTrackedDialogAsync('Key Backup', 'Key Backup', import('../../../async-components/views/dialogs/keybackup/CreateKeyBackupDialog'), @@ -135,7 +160,6 @@ export default class KeyBackupPanel extends React.PureComponent { } _deleteBackup = () => { - const QuestionDialog = sdk.getComponent('dialogs.QuestionDialog'); Modal.createTrackedDialog('Delete Backup', '', QuestionDialog, { title: _t('Delete Backup'), description: _t( @@ -155,41 +179,58 @@ export default class KeyBackupPanel extends React.PureComponent { } _restoreBackup = async () => { - const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog'); Modal.createTrackedDialog( 'Restore Backup', '', RestoreKeyBackupDialog, null, null, /* priority = */ false, /* static = */ true, ); } - render() { - const Spinner = sdk.getComponent("elements.Spinner"); - const AccessibleButton = sdk.getComponent("elements.AccessibleButton"); - const encryptedMessageAreEncrypted = _t( - "Encrypted messages are secured with end-to-end encryption. " + - "Only you and the recipient(s) have the keys to read these messages.", - ); + _resetSecretStorage = async () => { + this.setState({ error: null }); + try { + await accessSecretStorage(() => { }, /* forceReset = */ true); + } catch (e) { + console.error("Error resetting secret storage", e); + if (this._unmounted) return; + this.setState({ error: e }); + } + if (this._unmounted) return; + this._loadBackupStatus(); + } - if (this.state.error) { - return ( + render() { + const { + loading, + error, + backupKeyStored, + backupKeyCached, + backupKeyWellFormed, + secretStorageKeyInAccount, + secretStorageReady, + backupInfo, + backupSigStatus, + sessionsRemaining, + } = this.state; + + let statusDescription; + let extraDetailsTableRows; + let extraDetails; + const actions = []; + if (error) { + statusDescription = (
{_t("Unable to load key backup status")}
); - } else if (this.state.loading) { - return ; - } else if (this.state.backupInfo) { - let clientBackupStatus; + } else if (loading) { + statusDescription = ; + } else if (backupInfo) { let restoreButtonCaption = _t("Restore from Backup"); if (MatrixClientPeg.get().getKeyBackupEnabled()) { - clientBackupStatus =
-

{encryptedMessageAreEncrypted}

-

✅ {_t("This session is backing up your keys. ")}

-
; + statusDescription =

✅ {_t("This session is backing up your keys. ")}

; } else { - clientBackupStatus =
-

{encryptedMessageAreEncrypted}

+ statusDescription = <>

{_t( "This session is not backing up your keys, " + "but you do have an existing backup you can restore from " + @@ -200,19 +241,11 @@ export default class KeyBackupPanel extends React.PureComponent { "Connect this session to key backup before signing out to avoid " + "losing any keys that may only be on this session.", )}

-
; + ; restoreButtonCaption = _t("Connect this session to Key Backup"); } - let keyStatus; - if (this.state.backupKeyStored === true) { - keyStatus = _t("in secret storage"); - } else { - keyStatus = _t("not stored"); - } - let uploadStatus; - const { sessionsRemaining } = this.state; if (!MatrixClientPeg.get().getKeyBackupEnabled()) { // No upload status to show when backup disabled. uploadStatus = ""; @@ -226,17 +259,17 @@ export default class KeyBackupPanel extends React.PureComponent {
; } - let backupSigStatuses = this.state.backupSigStatus.sigs.map((sig, i) => { + let backupSigStatuses = backupSigStatus.sigs.map((sig, i) => { const deviceName = sig.device ? (sig.device.getDisplayName() || sig.device.deviceId) : null; const validity = sub => - + {sub} ; const verify = sub => - + {sub} ; - const device = sub => {deviceName}; + const device = sub => {deviceName}; const fromThisDevice = ( sig.device && sig.device.getFingerprint() === MatrixClientPeg.get().getDeviceEd25519Key() @@ -307,60 +340,123 @@ export default class KeyBackupPanel extends React.PureComponent { {sigStatus} ; }); - if (this.state.backupSigStatus.sigs.length === 0) { + if (backupSigStatus.sigs.length === 0) { backupSigStatuses = _t("Backup is not signed by any of your sessions"); } let trustedLocally; - if (this.state.backupSigStatus.trusted_locally) { + if (backupSigStatus.trusted_locally) { trustedLocally = _t("This backup is trusted because it has been restored on this session"); } - let deleteBackupButton; - if (!isSecureBackupRequired()) { - deleteBackupButton = - {_t("Delete Backup")} - ; - } + extraDetailsTableRows = <> + + {_t("Backup version:")} + {backupInfo.version} + + + {_t("Algorithm:")} + {backupInfo.algorithm} + + ; - const buttonRow = ( -
- - {restoreButtonCaption} -     - {deleteBackupButton} -
+ extraDetails = <> + {uploadStatus} +
{backupSigStatuses}
+
{trustedLocally}
+ ; + + actions.push( + + {restoreButtonCaption} + , ); - return
-
{clientBackupStatus}
-
- {_t("Advanced")} -
{_t("Backup version: ")}{this.state.backupInfo.version}
-
{_t("Algorithm: ")}{this.state.backupInfo.algorithm}
-
{_t("Backup key stored: ")}{keyStatus}
- {uploadStatus} -
{backupSigStatuses}
-
{trustedLocally}
-
- {buttonRow} -
; + if (!isSecureBackupRequired()) { + actions.push( + + {_t("Delete Backup")} + , + ); + } } else { - return
-
-

{_t( - "Your keys are not being backed up from this session.", {}, - {b: sub => {sub}}, - )}

-

{encryptedMessageAreEncrypted}

-

{_t("Back up your keys before signing out to avoid losing them.")}

-
-
- - {_t("Start using Key Backup")} - -
+ statusDescription = <> +

{_t( + "Your keys are not being backed up from this session.", {}, + {b: sub => {sub}}, + )}

+

{_t("Back up your keys before signing out to avoid losing them.")}

+ ; + actions.push( + + {_t("Set up")} + , + ); + } + + if (secretStorageKeyInAccount) { + actions.push( + + {_t("Reset")} + , + ); + } + + let backupKeyWellFormedText = ""; + if (backupKeyCached) { + backupKeyWellFormedText = ", "; + if (backupKeyWellFormed) { + backupKeyWellFormedText += _t("well formed"); + } else { + backupKeyWellFormedText += _t("unexpected type"); + } + } + + let actionRow; + if (actions.length) { + actionRow =
+ {actions}
; } + + return ( +
+

{_t( + "Back up your encryption keys with your account data in case you " + + "lose access to your sessions. Your keys will be secured with a " + + "unique Recovery Key.", + )}

+ {statusDescription} +
+ {_t("Advanced")} + + + + + + + + + + + + + + + + + + {extraDetailsTableRows} +
{_t("Backup key stored:")}{ + backupKeyStored === true ? _t("in secret storage") : _t("not stored") + }
{_t("Backup key cached:")} + {backupKeyCached ? _t("cached locally") : _t("not found locally")} + {backupKeyWellFormedText} +
{_t("Secret storage public key:")}{secretStorageKeyInAccount ? _t("in account data") : _t("not found")}
{_t("Secret storage:")}{secretStorageReady ? _t("ready") : _t("not ready")}
+ {extraDetails} +
+ {actionRow} +
+ ); } } diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js index 90dcc0b658..c25ac438e0 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.js @@ -29,6 +29,7 @@ import {sleep} from "../../../../../utils/promise"; import dis from "../../../../../dispatcher/dispatcher"; import {privateShouldBeEncrypted} from "../../../../../createRoom"; import {SettingLevel} from "../../../../../settings/SettingLevel"; +import SecureBackupPanel from "../../SecureBackupPanel"; export class IgnoredUser extends React.Component { static propTypes = { @@ -288,12 +289,11 @@ export default class SecurityUserSettingsTab extends React.Component { const SettingsFlag = sdk.getComponent('views.elements.SettingsFlag'); const EventIndexPanel = sdk.getComponent('views.settings.EventIndexPanel'); - const KeyBackupPanel = sdk.getComponent('views.settings.KeyBackupPanel'); - const keyBackup = ( + const secureBackup = (
- {_t("Key backup")} + {_t("Secure Backup")}
- +
); @@ -352,7 +352,7 @@ export default class SecurityUserSettingsTab extends React.Component {
{_t("Encryption")}
- {keyBackup} + {secureBackup} {eventIndex} {crossSigning} {this._renderCurrentDeviceInfo()} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 77cd8ef661..299079e14b 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -645,14 +645,10 @@ "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 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.", + "Cross-signing is ready for use.": "Cross-signing is ready for use.", "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", - "Bootstrap cross-signing and secret storage": "Bootstrap cross-signing and secret storage", - "well formed": "well formed", - "unexpected type": "unexpected type", + "Cross-signing is not set up.": "Cross-signing is not set up.", + "Reset": "Reset", "Cross-signing public keys:": "Cross-signing public keys:", "in memory": "in memory", "not found": "not found", @@ -663,9 +659,6 @@ "not found locally": "not found locally", "Self signing private key:": "Self signing private key:", "User signing private key:": "User signing private key:", - "Session backup key:": "Session backup key:", - "Secret storage public key:": "Secret storage public key:", - "in account data": "in account data", "Homeserver feature support:": "Homeserver feature support:", "exists": "exists", "Your homeserver does not support session management.": "Your homeserver does not support session management.", @@ -697,36 +690,6 @@ "Connecting to integration manager...": "Connecting to integration manager...", "Cannot connect to integration manager": "Cannot connect to integration manager", "The integration manager is offline or it cannot reach your homeserver.": "The integration manager is offline or it cannot reach your homeserver.", - "Delete Backup": "Delete Backup", - "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.": "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.", - "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", - "Unable to load key backup status": "Unable to load key backup status", - "Restore from Backup": "Restore from Backup", - "This session is backing up your keys. ": "This session is backing up your keys. ", - "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.": "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.", - "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.", - "Connect this session to Key Backup": "Connect this session to Key Backup", - "not stored": "not stored", - "Backing up %(sessionsRemaining)s keys...": "Backing up %(sessionsRemaining)s keys...", - "All keys backed up": "All keys backed up", - "Backup has a valid signature from this user": "Backup has a valid signature from this user", - "Backup has a invalid signature from this user": "Backup has a invalid signature from this user", - "Backup has a signature from unknown user with ID %(deviceId)s": "Backup has a signature from unknown user with ID %(deviceId)s", - "Backup has a signature from unknown session with ID %(deviceId)s": "Backup has a signature from unknown session with ID %(deviceId)s", - "Backup has a valid signature from this session": "Backup has a valid signature from this session", - "Backup has an invalid signature from this session": "Backup has an invalid signature from this session", - "Backup has a valid signature from verified session ": "Backup has a valid signature from verified session ", - "Backup has a valid signature from unverified session ": "Backup has a valid signature from unverified session ", - "Backup has an invalid signature from verified session ": "Backup has an invalid signature from verified session ", - "Backup has an invalid signature from unverified session ": "Backup has an invalid signature from unverified session ", - "Backup is not signed by any of your sessions": "Backup is not signed by any of your sessions", - "This backup is trusted because it has been restored on this session": "This backup is trusted because it has been restored on this session", - "Backup version: ": "Backup version: ", - "Algorithm: ": "Algorithm: ", - "Backup key stored: ": "Backup key stored: ", - "Your keys are not being backed up from this session.": "Your keys are not being backed up from this session.", - "Back up your keys before signing out to avoid losing them.": "Back up your keys before signing out to avoid losing them.", - "Start using Key Backup": "Start using Key Backup", "Error saving email notification preferences": "Error saving email notification preferences", "An error occurred whilst saving your email notification preferences.": "An error occurred whilst saving your email notification preferences.", "Keywords": "Keywords", @@ -758,6 +721,43 @@ "Display Name": "Display Name", "Profile picture": "Profile picture", "Save": "Save", + "Delete Backup": "Delete Backup", + "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.": "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.", + "Unable to load key backup status": "Unable to load key backup status", + "Restore from Backup": "Restore from Backup", + "This session is backing up your keys. ": "This session is backing up your keys. ", + "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.": "This session is not backing up your keys, but you do have an existing backup you can restore from and add to going forward.", + "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.": "Connect this session to key backup before signing out to avoid losing any keys that may only be on this session.", + "Connect this session to Key Backup": "Connect this session to Key Backup", + "Backing up %(sessionsRemaining)s keys...": "Backing up %(sessionsRemaining)s keys...", + "All keys backed up": "All keys backed up", + "Backup has a valid signature from this user": "Backup has a valid signature from this user", + "Backup has a invalid signature from this user": "Backup has a invalid signature from this user", + "Backup has a signature from unknown user with ID %(deviceId)s": "Backup has a signature from unknown user with ID %(deviceId)s", + "Backup has a signature from unknown session with ID %(deviceId)s": "Backup has a signature from unknown session with ID %(deviceId)s", + "Backup has a valid signature from this session": "Backup has a valid signature from this session", + "Backup has an invalid signature from this session": "Backup has an invalid signature from this session", + "Backup has a valid signature from verified session ": "Backup has a valid signature from verified session ", + "Backup has a valid signature from unverified session ": "Backup has a valid signature from unverified session ", + "Backup has an invalid signature from verified session ": "Backup has an invalid signature from verified session ", + "Backup has an invalid signature from unverified session ": "Backup has an invalid signature from unverified session ", + "Backup is not signed by any of your sessions": "Backup is not signed by any of your sessions", + "This backup is trusted because it has been restored on this session": "This backup is trusted because it has been restored on this session", + "Backup version:": "Backup version:", + "Algorithm:": "Algorithm:", + "Your keys are not being backed up from this session.": "Your keys are not being backed up from this session.", + "Back up your keys before signing out to avoid losing them.": "Back up your keys before signing out to avoid losing them.", + "well formed": "well formed", + "unexpected type": "unexpected type", + "Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Recovery Key.": "Back up your encryption keys with your account data in case you lose access to your sessions. Your keys will be secured with a unique Recovery Key.", + "Backup key stored:": "Backup key stored:", + "not stored": "not stored", + "Backup key cached:": "Backup key cached:", + "Secret storage public key:": "Secret storage public key:", + "in account data": "in account data", + "Secret storage:": "Secret storage:", + "ready": "ready", + "not ready": "not ready", "Identity Server URL must be HTTPS": "Identity Server URL must be HTTPS", "Not a valid Identity Server (status code %(code)s)": "Not a valid Identity Server (status code %(code)s)", "Could not connect to Identity Server": "Could not connect to Identity Server", @@ -904,7 +904,7 @@ "Bulk options": "Bulk options", "Accept all %(invitedRooms)s invites": "Accept all %(invitedRooms)s invites", "Reject all %(invitedRooms)s invites": "Reject all %(invitedRooms)s invites", - "Key backup": "Key backup", + "Secure Backup": "Secure Backup", "Message search": "Message search", "Cross-signing": "Cross-signing", "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.": "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.", @@ -946,7 +946,6 @@ "Uploaded sound": "Uploaded sound", "Sounds": "Sounds", "Notification sound": "Notification sound", - "Reset": "Reset", "Set a new custom sound": "Set a new custom sound", "Browse": "Browse", "Change room avatar": "Change room avatar", @@ -1168,6 +1167,7 @@ "%(roomName)s is not accessible at this time.": "%(roomName)s is not accessible at this time.", "Try again later, or ask a room admin to check if you have access.": "Try again later, or ask a room admin to check if you have access.", "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.": "%(errcode)s was returned while trying to access the room. If you think you're seeing this message in error, please submit a bug report.", + "Start using Key Backup": "Start using Key Backup", "Never lose encrypted messages": "Never lose encrypted messages", "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Messages in this room are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", "Securely back up your keys to avoid losing them. Learn more.": "Securely back up your keys to avoid losing them. Learn more.", @@ -1747,6 +1747,7 @@ "Clear cache and resync": "Clear cache and resync", "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!": "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!", "Updating %(brand)s": "Updating %(brand)s", + "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.": "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.", "I don't want my encrypted messages": "I don't want my encrypted messages", "Manually export keys": "Manually export keys", "You'll lose access to your encrypted messages": "You'll lose access to your encrypted messages",