cryptpadtab

encrypted notes in a browser tab  https://p.ce9e.org/cryptpadtab/
git clone https://git.ce9e.org/cryptpadtab.git

commit
d6419695aedd2b93627abfeacc33dee203382d6c
parent
7434ff79bd7a5e08378771867d1b230b79bbfe68
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-05-29 14:25
encrypt data

Diffstat

A static/crypto.js 29 +++++++++++++++++++++++++++++
M static/main.js 30 +++++++++++++++++++++---------

2 files changed, 50 insertions, 9 deletions


diff --git a/static/crypto.js b/static/crypto.js

@@ -0,0 +1,29 @@
   -1     1 export async function getKey(password) {
   -1     2 	var encoder = new TextEncoder();
   -1     3 	var encoded = encoder.encode(password);
   -1     4 	var hashed = await crypto.subtle.digest('SHA-256', encoded);
   -1     5 	return await crypto.subtle.importKey(
   -1     6 		'raw', hashed, 'AES-GCM', false, ['encrypt', 'decrypt'],
   -1     7 	);
   -1     8 }
   -1     9 
   -1    10 export async function encrypt(bytes, key) {
   -1    11 	var iv = crypto.getRandomValues(new Uint8Array(12));
   -1    12 	var encrypted = new Uint8Array(await crypto.subtle.encrypt(
   -1    13 		{name: 'AES-GCM', iv: iv}, key, bytes
   -1    14 	));
   -1    15 
   -1    16 	var result = new Uint8Array(iv.length + encrypted.length);
   -1    17 	result.set(iv, 0);
   -1    18 	result.set(encrypted, iv.length);
   -1    19 	return result;
   -1    20 }
   -1    21 
   -1    22 export async function decrypt(bytes, key) {
   -1    23 	var iv = bytes.slice(0, 12);
   -1    24 	var encrypted = bytes.slice(12);
   -1    25 
   -1    26 	return new Uint8Array(await crypto.subtle.decrypt(
   -1    27 		{name: 'AES-GCM', iv: iv}, key, encrypted
   -1    28 	));
   -1    29 }

diff --git a/static/main.js b/static/main.js

@@ -1,26 +1,38 @@
    1     1 import * as base64 from './base64.js';
   -1     2 import * as crypto from './crypto.js';
    2     3 import * as gzip from './gzip.js';
    3     4 
   -1     5 var password = window.prompt('Please enter the password');
   -1     6 var key = await crypto.getKey(password);
   -1     7 
    4     8 var encode = async function(text) {
    5     9 	var encoder = new TextEncoder();
    6    10 	var bytes = encoder.encode(text);
    7    -1 	return base64.encode(await gzip.compress(bytes));
   -1    11 	bytes = await gzip.compress(bytes);
   -1    12 	bytes = await crypto.encrypt(bytes, key);
   -1    13 	return base64.encode(bytes);
    8    14 };
    9    15 
   10    16 var decode = async function(string) {
   11    17 	var decoder = new TextDecoder();
   12    -1 	var bytes = await gzip.decompress(base64.decode(string));
   -1    18 	var bytes = base64.decode(string);
   -1    19 	bytes = await crypto.decrypt(bytes, key);
   -1    20 	bytes = await gzip.decompress(bytes);
   13    21 	return decoder.decode(bytes);
   14    22 };
   15    23 
   16    24 var textarea = document.querySelector('textarea');
   17    25 
   18    -1 decode(location.hash.substr(1)).then(text => {
   19    -1 	textarea.value = text;
   20    -1 });
   -1    26 if (location.hash.length) {
   -1    27 	try {
   -1    28 		textarea.value = await decode(location.hash.substr(1));
   -1    29 	} catch (e) {
   -1    30 		window.confirm('Decryption failed');
   -1    31 		console.exception(e);
   -1    32 	}
   -1    33 }
   21    34 
   22    -1 textarea.addEventListener('input', event => {
   23    -1 	encode(textarea.value).then(data => {
   24    -1 		history.replaceState(null, '', `#${data}`);
   25    -1 	});
   -1    35 textarea.addEventListener('input', async () => {
   -1    36 	var data = await encode(textarea.value);
   -1    37 	history.replaceState(null, '', `#${data}`);
   26    38 });