diff --git a/src/SuggestKeyRestoreHandler.js b/src/SuggestKeyRestoreHandler.js new file mode 100644 index 00000000000..3383889c1e1 --- /dev/null +++ b/src/SuggestKeyRestoreHandler.js @@ -0,0 +1,96 @@ +/* +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import sdk from './index'; +import Modal from './Modal'; + +export default class SuggestKeyRestoreHandler { + constructor(matrixClient) { + this._matrixClient = matrixClient; + } + + handleSuggestKeyRestore() { + const onVerifyDevice = () => { + const DeviceVerifyDialog = sdk.getComponent('views.dialogs.DeviceVerifyDialog'); + + Modal.createTrackedDialog('Key Restore', 'Starting verification', DeviceVerifyDialog, { + // userId: this.props.userId, + // device: this.state.deviceInfo, + onFinished: (verified) => { + if (verified) { + this.props.onFinished(); + } + }, + }); + }; + + const onRecoverFromBackup = () => { + // XXX: we need this so that you can get at it from UserSettings too + // * prompt for recovery key + // * Download the current backup version info from the server and check the key decrypts it okay. + // * Check that the public key for that backup version matches the recovery key + // * show a spinner + // * Download all the existing keys from the server + // * Decrypt them using the recovery key + // * Add them to the local store (which encrypts them as normal with "DEFAULT KEY" + // * Enable incremental backups for this device. + }; + + const onIgnoreSuggestion = () => { + }; + + const onFinished = () => { + this.suggestBackup(); + }; + + // FIXME: need a way to know if an account has ever touched E2E before. + // Perhaps we can extend toDevice to include a flag if it's the first time the + // server has ever sent a room_key to a client or something? + const virginAccount = false; + + if (virginAccount) { + this.suggestBackup(); + return; + } + + const SuggestKeyRestoreDialog = sdk.getComponent("dialogs.SuggestKeyRestoreDialog"); + Modal.createTrackedDialog('Key Restore', 'Key Restore', SuggestKeyRestoreDialog, { + matrixClient: this._matrixClient, + isOnlyDevice: false, // FIXME + hasOnlineBackup: false, // FIXME + onVerifyDevice: onVerifyDevice, + onRecoverFromBackup: onRecoverFromBackup, + onIgnoreSuggestion: onIgnoreSuggestion, + onFinished: onFinished, + }); + } + + suggestBackup() { + if (hasOnlineBackup) return; + + const onStartNewBackup = () => { + // XXX: we need this so that you can get at it from UserSettings too + // * Upload all their existing keys from their session store to the backup using the bulk upload API. + // (Having re-encrypted them using the backup keypair rather than the static one used to store them on disk) + }; + + const SuggestKeyBackupDialog = sdk.getComponent("dialogs.SuggestKeyBackupDialog"); + Modal.createTrackedDialog('Key Backup', 'Key Backup', SuggestKeyBackupDialog, { + onStartNewBackup: onStartNewBackup, + }); + } +} + diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 96e721f7ca1..4337cdfdbb4 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -1272,6 +1272,12 @@ export default React.createClass({ cli.on("crypto.roomKeyRequestCancellation", (req) => { krh.handleKeyRequestCancellation(req); }); + + const skrh = new SuggestKeyRestoreHandler(cli); + cli.on("crypto.suggestKeyRestore", () => { + skrh.handleSuggestKeyRestore(); + }); + cli.on("Room", (room) => { if (MatrixClientPeg.get().isCryptoEnabled()) { const blacklistEnabled = SettingsStore.getValueAt( diff --git a/src/components/views/dialogs/SuggestKeyBackupDialog.js b/src/components/views/dialogs/SuggestKeyBackupDialog.js new file mode 100644 index 00000000000..c2d6cfc60f5 --- /dev/null +++ b/src/components/views/dialogs/SuggestKeyBackupDialog.js @@ -0,0 +1,68 @@ +/* +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import Modal from '../../../Modal'; +import React from 'react'; +import PropTypes from 'prop-types'; +import sdk from '../../../index'; + +import { _t, _td } from '../../../languageHandler'; + +/** + * Dialog which asks the user whether they want to restore megolm keys + * from various sources when they first start using E2E on a new device. + */ +export default React.createClass({ + propTypes: { + onStartNewBackup: PropTypes.func.isRequired, + }, + + render: function() { + const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); + + return ( + +
+

To avoid ever losing your encrypted message history, you + can save your encryption keys on the server, protected by a recovery key. +

+

To maximise security, your recovery key is never stored by the app, + so you must store it yourself somewhere safe.

+

+

Warning: storing your encryption keys on the server means that + if someone gains access to your account and also steals your recovery key, + they will be able to read all of your encrypted conversation history. +

+ +

Do you wish to generate a recovery key and backup your encryption + keys on the server? + +

+ + +
+
+
+ ); + }, +}); diff --git a/src/components/views/dialogs/SuggestKeyRestoreDialog.js b/src/components/views/dialogs/SuggestKeyRestoreDialog.js new file mode 100644 index 00000000000..3419b6235c7 --- /dev/null +++ b/src/components/views/dialogs/SuggestKeyRestoreDialog.js @@ -0,0 +1,77 @@ +/* +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import Modal from '../../../Modal'; +import React from 'react'; +import PropTypes from 'prop-types'; +import sdk from '../../../index'; + +import { _t, _td } from '../../../languageHandler'; + +/** + * Dialog which asks the user whether they want to restore megolm keys + * from various sources when they first start using E2E on a new device. + */ +export default React.createClass({ + propTypes: { + matrixClient: PropTypes.object.isRequired, + isOnlyDevice: PropTypes.bool.isRequired, + hasOnlineBackup: PropTypes.bool.isRequired, + onVerifyDevice: PropTypes.func.isRequired, + onImportBackup: PropTypes.func.isRequired, + onRecoverFromBackup: PropTypes.func.isRequired, + onIgnoreSuggestion: PropTypes.func.isRequired, + }, + + render: function() { + const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); + + return ( + +
+

We don't have a way to decrypt older messages on this device.

+ +

Your options are:

+ +
  • + { !this.props.isOnlyDevice ?
      Verify this device from one or more of your other ones to automatically sync keys
    : '' } + { this.props.hasOnlineBackup ?
      Enter your recovery key to restore encryption keys from your online backup
    : '' } +
      Import encryption keys from an offline backup
    +
      Continue without restoring keys, syncing keys from your other devices on a best effort basis
    +
  • + +
    + + + + +
    +
    +
    + ); + }, +});