cryptpadtab

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

commit
d291c2f5ff8a125d1ec58a73ff8242fe73f4a8ae
parent
d6419695aedd2b93627abfeacc33dee203382d6c
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-05-29 14:50
combine everything into a single module

Diffstat

D static/base64.js 33 ---------------------------------
M static/crypto.js 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D static/gzip.js 19 -------------------
M static/main.js 22 ++--------------------

4 files changed, 72 insertions, 72 deletions


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

@@ -1,33 +0,0 @@
    1    -1 var table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
    2    -1 
    3    -1 export var encode = function(bytes) {
    4    -1 	var result = '';
    5    -1 	var push = x => result += table.charAt(x & 0b111111);
    6    -1 	for (let i = 0; i < bytes.length; i += 3) {
    7    -1 		var b1 = bytes[i];
    8    -1 		var b2 = bytes[i + 1];
    9    -1 		var b3 = bytes[i + 2];
   10    -1 
   11    -1 		push(b1 >> 2);
   12    -1 		push((b1 << 4) | (b2 >> 4));
   13    -1 		if (!isNaN(b2)) push((b2 << 2) | (b3 >> 6));
   14    -1 		if (!isNaN(b3)) push(b3);
   15    -1 	}
   16    -1 	return result;
   17    -1 };
   18    -1 
   19    -1 export var decode = function(string) {
   20    -1 	var result = [];
   21    -1 	for (let i = 0; i < string.length; i += 4) {
   22    -1 		var e1 = table.indexOf(string[i]);
   23    -1 		var e2 = table.indexOf(string[i + 1]);
   24    -1 		var e3 = table.indexOf(string[i + 2]);
   25    -1 		var e4 = table.indexOf(string[i + 3]);
   26    -1 
   27    -1 		result.push((e1 << 2) | (e2 >> 4));
   28    -1 		if (e3 !== -1) result.push((e2 << 4) | (e3 >> 2));
   29    -1 		if (e4 !== -1) result.push((e3 << 6) | e4);
   30    -1 	}
   31    -1 	// will truncate the values automatically
   32    -1 	return new Uint8Array(result);
   33    -1 };

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

@@ -1,3 +1,57 @@
   -1     1 var b64table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
   -1     2 
   -1     3 export function b64encode(bytes) {
   -1     4 	var result = '';
   -1     5 	var push = x => result += b64table.charAt(x & 0b111111);
   -1     6 	for (let i = 0; i < bytes.length; i += 3) {
   -1     7 		var b1 = bytes[i];
   -1     8 		var b2 = bytes[i + 1];
   -1     9 		var b3 = bytes[i + 2];
   -1    10 
   -1    11 		push(b1 >> 2);
   -1    12 		push((b1 << 4) | (b2 >> 4));
   -1    13 		if (!isNaN(b2)) push((b2 << 2) | (b3 >> 6));
   -1    14 		if (!isNaN(b3)) push(b3);
   -1    15 	}
   -1    16 	return result;
   -1    17 }
   -1    18 
   -1    19 export function b64decode(string) {
   -1    20 	var result = [];
   -1    21 	for (let i = 0; i < string.length; i += 4) {
   -1    22 		var e1 = b64table.indexOf(string[i]);
   -1    23 		var e2 = b64table.indexOf(string[i + 1]);
   -1    24 		var e3 = b64table.indexOf(string[i + 2]);
   -1    25 		var e4 = b64table.indexOf(string[i + 3]);
   -1    26 
   -1    27 		result.push((e1 << 2) | (e2 >> 4));
   -1    28 		if (e3 !== -1) result.push((e2 << 4) | (e3 >> 2));
   -1    29 		if (e4 !== -1) result.push((e3 << 6) | e4);
   -1    30 	}
   -1    31 	// will truncate the values automatically
   -1    32 	return new Uint8Array(result);
   -1    33 }
   -1    34 
   -1    35 async function applyStream(bytes, stream) {
   -1    36 	var readableStream = new ReadableStream({
   -1    37 		start(controller) {
   -1    38 			controller.enqueue(bytes);
   -1    39 			controller.close();
   -1    40 		}
   -1    41 	});
   -1    42 	var resultStream = await readableStream.pipeThrough(stream);
   -1    43 	var result = await new Response(resultStream).arrayBuffer();
   -1    44 	return new Uint8Array(result);
   -1    45 }
   -1    46 
   -1    47 export async function compress(bytes) {
   -1    48 	return await applyStream(bytes, new CompressionStream('gzip'));
   -1    49 }
   -1    50 
   -1    51 export async function decompress(bytes) {
   -1    52 	return await applyStream(bytes, new DecompressionStream('gzip'));
   -1    53 }
   -1    54 
    1    55 export async function getKey(password) {
    2    56 	var encoder = new TextEncoder();
    3    57 	var encoded = encoder.encode(password);
@@ -27,3 +81,19 @@ export async function decrypt(bytes, key) {
   27    81 		{name: 'AES-GCM', iv: iv}, key, encrypted
   28    82 	));
   29    83 }
   -1    84 
   -1    85 export async function encryptText(text, key) {
   -1    86 	var encoder = new TextEncoder();
   -1    87 	var bytes = encoder.encode(text);
   -1    88 	bytes = await compress(bytes);
   -1    89 	bytes = await encrypt(bytes, key);
   -1    90 	return b64encode(bytes);
   -1    91 }
   -1    92 
   -1    93 export async function decryptText(string, key) {
   -1    94 	var decoder = new TextDecoder();
   -1    95 	var bytes = b64decode(string);
   -1    96 	bytes = await decrypt(bytes, key);
   -1    97 	bytes = await decompress(bytes);
   -1    98 	return decoder.decode(bytes);
   -1    99 }

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

@@ -1,19 +0,0 @@
    1    -1 async function applyStream(bytes, stream) {
    2    -1 	var readableStream = new ReadableStream({
    3    -1 		start(controller) {
    4    -1 			controller.enqueue(bytes);
    5    -1 			controller.close();
    6    -1 		}
    7    -1 	});
    8    -1 	var resultStream = await readableStream.pipeThrough(stream);
    9    -1 	var result = await new Response(resultStream).arrayBuffer();
   10    -1 	return new Uint8Array(result);
   11    -1 }
   12    -1 
   13    -1 export async function compress(bytes) {
   14    -1 	return await applyStream(bytes, new CompressionStream('gzip'));
   15    -1 }
   16    -1 
   17    -1 export async function decompress(bytes) {
   18    -1 	return await applyStream(bytes, new DecompressionStream('gzip'));
   19    -1 }

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

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