--- /dev/null
+export default async function decrypt(content, password) {
+ const encodedPassword = new TextEncoder().encode(password);
+
+ const contentBuffer = Uint8Array.from(atob(content), c => c.charCodeAt(0));
+ const salt = new Uint8Array(32);
+ const iv = new Uint8Array(32);
+ const ciphertext = new Uint8Array(contentBuffer.byteLength - 64);
+ salt.set(contentBuffer.slice(0, 32));
+ iv.set(contentBuffer.slice(32, 64));
+ ciphertext.set(contentBuffer.slice(64));
+
+ const keyMaterial = await crypto.subtle.importKey(
+ 'raw',
+ encodedPassword,
+ 'PBKDF2',
+ false,
+ ['deriveKey'],
+ );
+
+ const key = await crypto.subtle.deriveKey(
+ {
+ name: 'PBKDF2',
+ hash: 'SHA-512',
+ salt,
+ iterations: 400_000,
+ },
+ keyMaterial,
+ { name: 'AES-GCM', length: 256 },
+ false,
+ ['decrypt']
+ );
+
+ const encodedPlaintext = new Uint8Array(await crypto.subtle.decrypt(
+ { name: 'AES-GCM', iv },
+ key,
+ ciphertext,
+ ));
+
+ const plaintext = new TextDecoder().decode(encodedPlaintext);
+
+ return plaintext;
+}
return content;
}
+ const { default: decrypt } = await import('/decrypt.js');
const template = await fetch('/template.html').then(r => r.text());
document.querySelector('form').addEventListener('submit', async e => {
e.preventDefault();
const password = data.get('password');
const encrypted = await encrypt(content, password);
- const output = template.replace("const content = 'DO_NOT_MODIFY_THIS_LINE';", `const content = '${encrypted}';`);
+ const scriptInjection = `<script>const content = '${encrypted}'; ${decrypt.toString()}<\/script>`;
+ const output = template.replace('<!-- SCRIPT INJECTION -->', scriptInjection);
e.target.elements.output.textContent = output;
});
</script>
</form>
</main>
+ <!-- SCRIPT INJECTION -->
<script>
- const content = 'DO_NOT_MODIFY_THIS_LINE';
-
- async function decrypt(content, password) {
- const encoder = new TextEncoder();
- const encodedPassword = encoder.encode(password);
-
- const contentBuffer = Uint8Array.from(atob(content), c => c.charCodeAt(0));
- const salt = new Uint8Array(32);
- const iv = new Uint8Array(32);
- const ciphertext = new Uint8Array(contentBuffer.byteLength - 64);
- salt.set(contentBuffer.slice(0, 32));
- iv.set(contentBuffer.slice(32, 64));
- ciphertext.set(contentBuffer.slice(64));
-
- const keyMaterial = await crypto.subtle.importKey(
- 'raw',
- encodedPassword,
- 'PBKDF2',
- false,
- ['deriveKey'],
- );
-
- const key = await crypto.subtle.deriveKey(
- {
- name: 'PBKDF2',
- hash: 'SHA-512',
- salt,
- iterations: 400_000,
- },
- keyMaterial,
- { 'name': 'AES-GCM', 'length': 256 },
- false,
- ['decrypt']
- );
-
- const encodedPlaintext = new Uint8Array(await crypto.subtle.decrypt(
- { name: 'AES-GCM', iv },
- key,
- ciphertext,
- ));
-
- const plaintext = new TextDecoder().decode(encodedPlaintext);
-
- return plaintext;
- }
-
document.querySelector('form').addEventListener('submit', async e => {
e.preventDefault();
+ const password = new FormData(e.target).get('password');
+ const newDocument = await decrypt(content, password);
- const data = new FormData(e.target);
- const password = data.get('password');
-
- document.querySelector('html').innerHTML = await decrypt(content, password);
+ document.open();
+ document.write(newDocument);
+ document.close();
});
</script>
</body>