Huilensolis / memoir

Memoir is a web editor for journaling and documenting your reflections.
https://memoir-oak.vercel.app
15 stars 1 forks source link

feat(app): encrypt data #217

Open Huilensolis opened 2 weeks ago

Huilensolis commented 2 weeks ago

learn AES encryption

Huilensolis commented 2 weeks ago
guiprav2 commented 2 weeks ago

encrypt/decrypt utilities example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AES Encryption/Decryption</title>
    <script>
        async function getKeyMaterial(password) {
            const encoder = new TextEncoder();
            return window.crypto.subtle.importKey(
                "raw",
                encoder.encode(password),
                { name: "PBKDF2" },
                false,
                ["deriveKey"]
            );
        }

        async function getKey(keyMaterial, salt) {
            return window.crypto.subtle.deriveKey(
                {
                    name: "PBKDF2",
                    salt: salt,
                    iterations: 100000,
                    hash: "SHA-256"
                },
                keyMaterial,
                { name: "AES-GCM", length: 256 },
                false,
                ["encrypt", "decrypt"]
            );
        }

        function arrayBufferToBase64(buffer) {
            let binary = '';
            const bytes = new Uint8Array(buffer);
            const len = bytes.byteLength;
            for (let i = 0; i < len; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            return window.btoa(binary);
        }

        function base64ToArrayBuffer(base64) {
            const binary = window.atob(base64);
            const len = binary.length;
            const bytes = new Uint8Array(len);
            for (let i = 0; i < len; i++) {
                bytes[i] = binary.charCodeAt(i);
            }
            return bytes.buffer;
        }

        async function encrypt(payload, password) {
            const keyMaterial = await getKeyMaterial(password);
            const salt = window.crypto.getRandomValues(new Uint8Array(16));
            const key = await getKey(keyMaterial, salt);
            const iv = window.crypto.getRandomValues(new Uint8Array(12));
            const encoder = new TextEncoder();
            const data = encoder.encode(payload);
            const encryptedData = await window.crypto.subtle.encrypt(
                {
                    name: "AES-GCM",
                    iv: iv
                },
                key,
                data
            );
            const encryptedContent = new Uint8Array(encryptedData);
            const result = new Uint8Array(salt.length + iv.length + encryptedContent.length);
            result.set(salt, 0);
            result.set(iv, salt.length);
            result.set(encryptedContent, salt.length + iv.length);
            return arrayBufferToBase64(result.buffer);
        }

        async function decrypt(payload, password) {
            const keyMaterial = await getKeyMaterial(password);
            const data = base64ToArrayBuffer(payload);
            const salt = data.slice(0, 16);
            const iv = data.slice(16, 28);
            const encryptedData = data.slice(28);
            const key = await getKey(keyMaterial, salt);
            const decryptedData = await window.crypto.subtle.decrypt(
                {
                    name: "AES-GCM",
                    iv: iv
                },
                key,
                encryptedData
            );
            const decoder = new TextDecoder();
            return decoder.decode(decryptedData);
        }

        // Example usage:
        async function exampleUsage() {
            const text = "Hello, world!";
            const password = "securepassword";
            const encrypted = await encrypt(text, password);
            console.log("Encrypted:", encrypted);
            const decrypted = await decrypt(encrypted, password);
            console.log("Decrypted:", decrypted);
        }

        window.onload = exampleUsage;
    </script>
</head>
<body>
    <h1>AES Encryption/Decryption Example</h1>
    <p>Check the console for results.</p>
</body>
</html>