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;;