This commit is contained in:
2020-08-22 14:56:41 +02:00
parent 79d89f266a
commit 26028445bf
16 changed files with 315 additions and 176 deletions

106
src/contexts/Decryption.tsx Normal file
View File

@@ -0,0 +1,106 @@
import React, { useState, useCallback, useContext, createContext, useEffect } from 'react';
import * as openpgp from 'openpgp';
import GithubContext from './Github';
import FileType from '../types/File';
import { createFile } from '../helpers/files';
interface DecryptionContextType {
publicKey: string | undefined;
files: {[id: string]: FileType};
addFile: (file: File) => Promise<void>;
deleteFile: (id: string) => void;
}
const DecryptionContext = createContext<DecryptionContextType>({
publicKey: undefined,
files: {},
addFile: async () => { throw new Error('Not using provider'); },
deleteFile: async () => { throw new Error('Not using provider'); },
});
const decrypt = async (privateKey: string, keys: string[], content: string) => {
const armoredKeys = await Promise.all(keys.map(openpgp.key.readArmored));
const message = openpgp.message.fromText(content);
const encrypted = await openpgp.decrypt({
message,
privateKeys: [...(await openpgp.key.readArmored(privateKey)).keys],
publicKeys: armoredKeys.reduce<any>((output, key: any) => [...output, ...key.keys], []),
});
const { data } = encrypted;
const blob = new Blob([data], {
type: 'text/text',
});
return blob;
};
const DecryptionProvider: React.FC = ({
children,
}) => {
const { username, keys } = useContext(GithubContext);
const [privateKey, setPrivateKey] = useState<string | undefined>(undefined);
const [publicKey, setPublicKey] = useState<string | undefined>(undefined);
const [files, setFiles] = useState<DecryptionContextType['files']>({});
const deleteFile = useCallback((id: string) => {
delete files[id];
setFiles({
...files,
});
}, [files]);
useEffect(() => {
const run = async () => {
const currentRawKey = localStorage.getItem('key');
if (currentRawKey) {
setPrivateKey(currentRawKey);
const key = await openpgp.key.readArmored(currentRawKey);
setPublicKey(key.keys[0].toPublic().armor());
} else {
const key = await openpgp.generateKey({
userIds: [{ name: 'unknown unknown', email: 'unknown@unknown.foo'}],
curve: 'ed25519',
});
setPrivateKey(key.privateKeyArmored);
setPublicKey(key.publicKeyArmored);
localStorage.setItem('key', key.privateKeyArmored);
}
};
run();
}, []);
const addFile = useCallback(async (file: File) => {
if (!keys || !privateKey) return;
const addedFile = createFile(setFiles, file.name);
const reader = new FileReader()
reader.onabort = addedFile.setFailed,
reader.onerror = addedFile.setFailed,
reader.onload = () => {
addedFile.setContent(
decrypt(privateKey, keys, reader.result as string),
);
}
reader.readAsText(file)
}, [keys, username]);
return (
<DecryptionContext.Provider
value={{
publicKey,
files,
addFile,
deleteFile,
}}
>
{children}
</DecryptionContext.Provider>
);
};
export {
DecryptionProvider,
};
export default DecryptionContext;;

View File

@@ -1,16 +1,8 @@
import React, { useState, useCallback, useContext, createContext } from 'react';
import * as openpgp from 'openpgp';
import { nanoid } from 'nanoid';
import { message } from 'antd';
import GithubContext from './Github';
export interface FileType {
name: string;
reciever: string;
status: 'encrypting' | 'failed' | 'encrypted';
error?: any;
link?: Blob;
}
import { createFile } from '../helpers/files';
import FileType from '../types/File';
interface EncryptionContextType {
files: {[id: string]: FileType};
@@ -55,74 +47,27 @@ const EncryptionProvider: React.FC = ({
});
}, [files]);
const add = (name: string) => {
const id = nanoid();
const file: FileType = {
name: `${name}.asc`,
reciever: username,
status: 'encrypting',
};
setFiles(files => ({
...files,
[id]: file,
}));
const setError = (err: any) => {
console.error(err);
setFiles(files => ({
...files,
[id]: {
...files[id],
status: 'failed',
error: err,
},
}));
message.error(`Failed to encrypt ${name}`);
};
const setContent = (text: string, keys: string[]) => {
const run = async () => {
try {
const encrypted = await encrypt(keys, text);
setFiles(files => ({
...files,
[id]: {
...files[id],
link: encrypted,
status: 'encrypted'
},
}));
message.success(`Done encrypting ${name}`);
} catch (err) {
setError(err);
}
};
run();
};
return {
setContent,
setError,
};
}
const addFile = useCallback(async (file: File) => {
if (!keys) return;
const addedFile = add(file.name);
const addedFile = createFile(setFiles, `${file.name}.acs`);
const reader = new FileReader()
reader.onabort = addedFile.setError,
reader.onerror = addedFile.setError,
reader.onabort = addedFile.setFailed,
reader.onerror = addedFile.setFailed,
reader.onload = () => {
addedFile.setContent(reader.result as string, keys);
addedFile.setContent(
encrypt(keys, reader.result as string),
);
}
reader.readAsText(file)
}, [keys, username]);
const addText = useCallback(async (text: string, name: string) => {
if (!keys) return;
const file = add(`${name}.txt`);
file.setContent(text, keys);
const file = createFile(setFiles, `${name}.txt.asc`);
file.setContent(
encrypt(keys, text),
);
}, [keys, username]);
return (