implement encryption of secret text
This commit is contained in:
parent
8899fbb368
commit
04225c44aa
|
@ -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>
|
||||||
|
|
|
@ -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/**/*",
|
||||||
|
|
Loading…
Reference in New Issue