/* eslint-disable react/jsx-one-expression-per-line */ import React, { useState } from 'react'; import './CrossSigning.scss'; import FileSaver from 'file-saver'; import { Formik } from 'formik'; import { twemojify } from '../../../util/twemojify'; import initMatrix from '../../../client/initMatrix'; import { openReusableDialog } from '../../../client/action/navigation'; import { copyToClipboard } from '../../../util/common'; import { clearSecretStorageKeys } from '../../../client/state/secretStorageKeys'; import Text from '../../atoms/text/Text'; import Button from '../../atoms/button/Button'; import Input from '../../atoms/input/Input'; import Spinner from '../../atoms/spinner/Spinner'; import SettingTile from '../../molecules/setting-tile/SettingTile'; import { authRequest } from './AuthRequest'; import { useCrossSigningStatus } from '../../hooks/useCrossSigningStatus'; const failedDialog = () => { const renderFailure = (requestClose) => (
{twemojify('❌')} Failed to setup cross signing. Please try again.
); openReusableDialog( Setup cross signing, renderFailure, ); }; const securityKeyDialog = (key) => { const downloadKey = () => { const blob = new Blob([key.encodedPrivateKey], { type: 'text/plain;charset=us-ascii', }); FileSaver.saveAs(blob, 'security-key.txt'); }; const copyKey = () => { copyToClipboard(key.encodedPrivateKey); }; const renderSecurityKey = () => (
Please save this security key somewhere safe. {key.encodedPrivateKey}
); // Download automatically. downloadKey(); openReusableDialog( Security Key, () => renderSecurityKey(), ); }; function CrossSigningSetup() { const initialValues = { phrase: '', confirmPhrase: '' }; const [genWithPhrase, setGenWithPhrase] = useState(undefined); const setup = async (securityPhrase = undefined) => { const mx = initMatrix.matrixClient; setGenWithPhrase(typeof securityPhrase === 'string'); const recoveryKey = await mx.createRecoveryKeyFromPassphrase(securityPhrase); clearSecretStorageKeys(); await mx.bootstrapSecretStorage({ createSecretStorageKey: async () => recoveryKey, setupNewKeyBackup: true, setupNewSecretStorage: true, }); const authUploadDeviceSigningKeys = async (makeRequest) => { const isDone = await authRequest('Setup cross signing', async (auth) => { await makeRequest(auth); }); setTimeout(() => { if (isDone) securityKeyDialog(recoveryKey); else failedDialog(); }); }; await mx.bootstrapCrossSigning({ authUploadDeviceSigningKeys, setupNewCrossSigning: true, }); }; const validator = (values) => { const errors = {}; if (values.phrase === '12345678') { errors.phrase = 'How about 87654321 ?'; } if (values.phrase === '87654321') { errors.phrase = 'Your are playing with 🔥'; } const PHRASE_REGEX = /^([^\s]){8,127}$/; if (values.phrase.length > 0 && !PHRASE_REGEX.test(values.phrase)) { errors.phrase = 'Phrase must contain 8-127 characters with no space.'; } if (values.confirmPhrase.length > 0 && values.confirmPhrase !== values.phrase) { errors.confirmPhrase = 'Phrase don\'t match.'; } return errors; }; return (
We will generate a Security Key, which you can use to manage messages backup and session verification. {genWithPhrase !== false && } {genWithPhrase === false && }
OR setup(values.phrase)} validate={validator} > {({ values, errors, handleChange, handleSubmit, }) => (
Alternatively you can also set a Security Phrase so you don't have to remember long Security Key, and optionally save the Key as backup. {errors.phrase && {errors.phrase}} {errors.confirmPhrase && {errors.confirmPhrase}} {genWithPhrase !== true && } {genWithPhrase === true && } )}
); } const setupDialog = () => { openReusableDialog( Setup cross signing, () => , ); }; function CrossSigningReset() { return (
{twemojify('✋🧑‍🚒🤚')} Resetting cross-signing keys is permanent. Anyone you have verified with will see security alerts and your message backup will lost. You almost certainly do not want to do this, unless you have lost Security Key or Phrase and every session you can cross-sign from.
); } const resetDialog = () => { openReusableDialog( Reset cross signing, () => , ); }; function CrossSignin() { const isCSEnabled = useCrossSigningStatus(); return ( Setup to verify and keep track of all your sessions. Also required to backup encrypted message.} options={( isCSEnabled ? : )} /> ); } export default CrossSignin;