mirror of
https://github.com/morten-olsen/parcel.git
synced 2026-02-08 01:36:24 +01:00
sec
This commit is contained in:
106
src/contexts/Decryption.tsx
Normal file
106
src/contexts/Decryption.tsx
Normal 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;;
|
||||
Reference in New Issue
Block a user