implement encryption of secret text

This commit is contained in:
Silas 2021-11-29 20:51:17 -05:00
parent 8899fbb368
commit 04225c44aa
Signed by: silentsilas
GPG Key ID: 4199EFB7DAA34349
2 changed files with 59 additions and 2 deletions

View File

@ -1,11 +1,13 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { ProgressIndicator, Header2, Button, IconArrow, Label, FileInput, TextArea, CenteredContainer, Spacer, TextAlignWrapper, GlobalStyle } from '@intended/intended-ui'; import { ProgressIndicator, Header2, Button, IconArrow, Label, FileInput, TextArea, CenteredContainer, Spacer, TextAlignWrapper, GlobalStyle } from '@intended/intended-ui';
import HexMix from "../utils/hexmix";
const JustPage = () => { const JustPage = () => {
const [secretInput, setSecretInput] = useState(""); const [secretInput, setSecretInput] = useState("");
const [fileInput, setFileInput] = useState<File | null>(null); const [fileInput, setFileInput] = useState<File | null>(null);
const [fileName, setFileName] = useState(""); const [fileName, setFileName] = useState("");
const [encryptedSecret, setEncryptedSecret] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setSecretInput(e.target.value); setSecretInput(e.target.value);
@ -17,6 +19,59 @@ const JustPage = () => {
setFileName(file.name); setFileName(file.name);
}; };
const postContents = async () => {
if (!window.crypto.subtle) {
alert('Browser does not support SubtleCrypto');
return;
}
const key = await window.crypto.subtle.generateKey(
{
name: 'AES-GCM',
length: 256
},
true,
['encrypt', 'decrypt']
);
const encoded = HexMix.stringToArrayBuffer(secretInput);
const iv = window.crypto.getRandomValues(new Uint8Array(16));
const exported = await window.crypto.subtle.exportKey('raw', key);
const encrypted = await window.crypto.subtle.encrypt(
{
name: 'AES-GCM',
iv
},
key,
encoded
);
// encrypted will be sent to lumen backend
HexMix.arrayBufferToString(encrypted, (result: string) => {
setEncryptedSecret(result);
});
const keyHex = HexMix.uint8ToHex(new Uint8Array(exported));
const ivHex = HexMix.uint8ToHex(iv);
const formData = new FormData();
const blobData = new Blob([encrypted]);
formData.append('blob', blobData);
formData.append('filetype', 'text/plain');
formData.append('filename', 'secret.txt');
try {
await fetch(`${window.location.origin}/just`, {
body: formData,
method: "POST"
});
const url = `${window.location.origin}/just/for#${keyHex}.${ivHex}`;
window.location.href = url
} catch (err: any) {
alert(err.message);
}
};
return ( return (
<React.StrictMode> <React.StrictMode>
<GlobalStyle /> <GlobalStyle />
@ -39,12 +94,13 @@ const JustPage = () => {
</TextAlignWrapper> </TextAlignWrapper>
<Spacer space="1.6rem" /> <Spacer space="1.6rem" />
<FileInput id="fileInput" value={fileName} handleFile={handleFile} /> <FileInput id="fileInput" value={fileName} handleFile={handleFile} />
{ encryptedSecret ? "" : encryptedSecret }
{ fileInput ? "" : ""} { fileInput ? "" : ""}
<Spacer space="4rem" /> <Spacer space="4rem" />
<div <div
style={{ display: "flex", justifyContent: "flex-end", width: "100%" }} style={{ display: "flex", justifyContent: "flex-end", width: "100%" }}
> >
<Button variant="secondary" onClick={() => window.location.href = "/just/for"}> <Button variant="secondary" onClick={postContents}>
<IconArrow arrowDirection="right" /> <IconArrow arrowDirection="right" />
</Button> </Button>
</div> </div>

View File

@ -10,7 +10,8 @@
"esModuleInterop": true, "esModuleInterop": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true "noUnusedParameters": true,
"lib": ["es2015", "dom"]
}, },
"exclude": [ "exclude": [
"/node_modules/**/*", "/node_modules/**/*",