aboutsummaryrefslogtreecommitdiff
path: root/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'index.html')
-rw-r--r--index.html194
1 files changed, 194 insertions, 0 deletions
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f4fe7a3
--- /dev/null
+++ b/index.html
@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html lang="en" data-theme="dark">
+
+<head>
+ <meta charset="UTF-8">
+ <meta name="description" content="AES-256 Encryption Example">
+ <title>Secure Paste</title>
+ <link rel="icon" href="./favicon.svg" type="image/svg+xml">
+ <link rel="stylesheet" href="./pico.min.css">
+</head>
+
+<body>
+ <main class="container">
+ <h1>paste-cgi</h1>
+
+ <form id="cryptoForm">
+ <label for="title">Title</label>
+ <input type="text" id="title" placeholder="Enter a title" required />
+
+ <label for="plaintext">Paste</label>
+ <textarea id="plaintext" rows="5" placeholder="Enter your paste" required></textarea>
+
+ <label for="pasteType">Type</label>
+ <select id="pasteType" onchange="togglePasteType()">
+ <option value="plain">Plain</option>
+ <option value="password">Password</option>
+ </select>
+
+ <div id="passwordField" style="display: none;">
+ <label for="password">Password</label>
+ <input type="password" id="password" placeholder="Enter your password" />
+ </div>
+
+ <label for="expiration">Expiration</label>
+ <select id="expiration">
+ <option value="never">Never</option>
+ <option value="burn_after_read">Burn after read</option>
+ <option value="10_minutes">10 minutes</option>
+ <option value="1_hour">1 hour</option>
+ <option value="1_day">1 Day</option>
+ <option value="1_week">1 Week</option>
+ <option value="2_weeks">2 Weeks</option>
+ <option value="1_month">1 Month</option>
+ <option value="6_months">6 Months</option>
+ <option value="1_year">1 Year</option>
+ </select>
+
+ <button type="button" id="encryptBtn" onclick="handlePaste()">Paste</button>
+ </form>
+
+ <div id="pasteUrlSection" style="display: none;">
+ <h3>Paste Url:</h3>
+ <input id="pasteUrl" readonly></textarea>
+ <button type="button" onclick="copyPaste()">Copy</button>
+ </div>
+ </main>
+
+ <script>
+ const pasteTypeConstant = "pasteType";
+ const passwordFieldConstant = "passwordField";
+ const passwordTypeConstant = "password";
+ const plainTypeConstant = "plain";
+ const titleConstant = "title";
+ const expirationConstant = "expiration";
+ const plaintextConstant = "plaintext";
+ const pasteUrlConstant = "pasteUrl"
+ const pasteUrlSectionConstant = "pasteUrlSection"
+
+ function copyPaste(){
+ var copyText = document.getElementById(pasteUrlConstant);
+
+ copyText.select();
+ copyText.setSelectionRange(0, 99999);
+
+ navigator.clipboard.writeText(copyText.value);
+ }
+
+ function togglePasteType() {
+ const passwordType = document.getElementById(pasteTypeConstant).value;
+ const passwordField = document.getElementById(passwordFieldConstant);
+ if (passwordType === passwordTypeConstant) {
+ passwordField.style.display = 'block';
+ } else {
+ passwordField.style.display = 'none';
+ }
+ }
+
+ async function deriveKey(password, salt) {
+ let encodedPassword = new TextEncoder().encode(password);
+ let baseKey = await window.crypto.subtle.importKey(
+ "raw",
+ encodedPassword,
+ { name: "PBKDF2" },
+ false,
+ ["deriveKey"],
+ );
+
+ let derivedKey = await window.crypto.subtle.deriveKey(
+ {
+ name: "PBKDF2",
+ salt: salt,
+ iterations: 600000,
+ hash: "SHA-256",
+ },
+ baseKey,
+ { name: "AES-GCM", length: 256 },
+ true,
+ ["encrypt", "decrypt"],
+ );
+
+ return derivedKey;
+ }
+
+ async function encryptData(data, password) {
+ let salt = window.crypto.getRandomValues(new Uint8Array(16));
+ let iv = window.crypto.getRandomValues(new Uint8Array(12));
+ let key = await deriveKey(password, salt);
+ let encodedData = new TextEncoder().encode(data);
+
+ let encryptedContent = await window.crypto.subtle.encrypt(
+ {
+ name: "AES-GCM",
+ iv: iv,
+ tagLength: 128,
+ },
+ key,
+ encodedData,
+ );
+
+ let ciphertext = encryptedContent.slice(
+ 0,
+ encryptedContent.byteLength - 16,
+ );
+ let authTag = encryptedContent.slice(encryptedContent.byteLength - 16);
+
+ return {
+ ciphertext: new Uint8Array(ciphertext),
+ iv: iv,
+ authTag: new Uint8Array(authTag),
+ salt: salt,
+ };
+ }
+
+ async function handlePaste() {
+ let type = document.getElementById(pasteTypeConstant).value;
+ let title = document.getElementById(titleConstant).value;
+ let expiration = document.getElementById(expirationConstant).value;
+ let plaintext = document.getElementById(plaintextConstant).value;
+ let password = document.getElementById(passwordTypeConstant).value;
+
+ let pasted_text = ""
+ if (type == plainTypeConstant) {
+ if (!plaintext || !title) return alert("Enter title and paste.");
+
+ pasted_text = plaintext
+ }
+ else {
+ if (!plaintext || !password || !title) return alert("Enter title, paste and password.");
+
+ let encrypted = await encryptData(plaintext, password);
+ pasted_text = btoa(JSON.stringify(encrypted))
+ }
+
+ let currentPath = window.location.origin;
+
+ try {
+ let response = await fetch(currentPath + "/submit", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ type: type,
+ title: title,
+ expiration: expiration,
+ pasted_text: pasted_text
+ }),
+ });
+
+ if (response.ok) {
+ let jsonResponse = await response.json();
+ document.getElementById(pasteUrlConstant).value = currentPath + "/get?id=" + jsonResponse.id;
+ document.getElementById(pasteUrlSectionConstant).style.display = 'block';
+ } else {
+ console.error("Failed to submit data. Status:", response.status);
+ }
+ } catch (error) {
+ console.error("Error making the POST request:", error);
+ }
+ }
+ </script>
+</body>
+
+</html> \ No newline at end of file