1 import { useState } from 'react';
3 import { c } from 'ttag';
5 import { Button } from '@proton/atoms';
6 import Form from '@proton/components/components/form/Form';
7 import type { ModalProps } from '@proton/components/components/modalTwo/Modal';
8 import Modal from '@proton/components/components/modalTwo/Modal';
9 import ModalContent from '@proton/components/components/modalTwo/ModalContent';
10 import ModalFooter from '@proton/components/components/modalTwo/ModalFooter';
11 import ModalHeader from '@proton/components/components/modalTwo/ModalHeader';
12 import type { PrivateKeyReference } from '@proton/crypto';
13 import { CryptoProxy } from '@proton/crypto';
14 import { useLoading } from '@proton/hooks';
15 import { KEY_FILE_EXTENSION } from '@proton/shared/lib/constants';
16 import downloadFile from '@proton/shared/lib/helpers/downloadFile';
17 import { passwordLengthValidator } from '@proton/shared/lib/helpers/formValidators';
18 import generateUID from '@proton/utils/generateUID';
19 import noop from '@proton/utils/noop';
21 import { InputFieldTwo, PasswordInputTwo, useFormErrors } from '../../../components';
22 import { useModals } from '../../../hooks';
23 import UnlockModal from '../../login/UnlockModal';
25 const handleExport = async (name: string, privateKey: PrivateKeyReference, password: string) => {
26 const fingerprint = privateKey.getFingerprint();
27 const filename = ['privatekey.', name, '-', fingerprint, KEY_FILE_EXTENSION].join('');
28 const armoredEncryptedKey = await CryptoProxy.exportPrivateKey({ privateKey: privateKey, passphrase: password });
29 const blob = new Blob([armoredEncryptedKey], { type: 'text/plain' });
30 downloadFile(blob, filename);
33 interface Props extends ModalProps {
35 privateKey: PrivateKeyReference;
36 onSuccess?: () => void;
39 const ExportPrivateKeyModal = ({ name, privateKey, onSuccess, onClose, ...rest }: Props) => {
40 const { createModal } = useModals();
41 const [loading, withLoading] = useLoading();
42 const { validator, onFormSubmit } = useFormErrors();
44 const [id] = useState(() => generateUID('exportKey'));
45 const [password, setPassword] = useState('');
47 const handleSubmit = async () => {
48 // Force a login since the private key is sensitive
49 await new Promise<string>((resolve, reject) => {
50 createModal(<UnlockModal onClose={() => reject()} onSuccess={resolve} />);
52 await handleExport(name, privateKey, password);
57 const handleClose = loading ? noop : onClose;
63 if (!onFormSubmit()) {
67 void withLoading(handleSubmit());
72 <ModalHeader title={c('Title').t`Export private key`} />
74 <div className="mb-4">
76 .t`This will download a file containing your private key. Protect this file by encrypting it with a password.`}
81 label={c('Label').t`Create password`}
82 placeholder={c('Placeholder').t`Password`}
85 error={validator([passwordLengthValidator(password)])}
90 .t`Store this password and file in a safe place. You’ll need them again to import your key.`}
94 <Button onClick={handleClose} disabled={loading}>
95 {c('Action').t`Cancel`}
98 <Button loading={loading} type="submit" color="norm">
99 {c('Action').t`Encrypt and export`}
106 export default ExportPrivateKeyModal;