Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 88x 88x 23x 23x 23x 23x 41x 41x 41x 41x 41x 41x 10x 10x 15x 15x 15x 15x 15x 15x | import {compress, decompress} from './compression' type StoredKey = {salt: Uint8Array; key: CryptoKey} export const keys: {[index: string]: StoredKey} = {} const encoder = new TextEncoder() async function getKey(name: string, password: string, salt: Uint8Array): Promise<StoredKey | undefined> { Eif (!(name in keys)) { const baseKey = await crypto.subtle.importKey('raw', encoder.encode(password), {name: 'PBKDF2'}, false, [ 'deriveKey', ]) keys[name] = { salt, key: await crypto.subtle.deriveKey( { name: 'PBKDF2', salt, iterations: 1e6, hash: 'SHA-256', }, baseKey, {name: 'AES-GCM', length: 256}, false, ['encrypt', 'decrypt'] ), } } return keys[name] } export async function encrypt(name: string, content: object, password?: string) { const key = password && !(name in keys) ? await getKey(name, password, crypto.getRandomValues(new Uint8Array(16))) : keys[name] Eif (key) { try { const iv = crypto.getRandomValues(new Uint8Array(12)) const encrypted = await crypto.subtle.encrypt( {name: 'AES-GCM', iv}, key.key, new Uint8Array(await (await compress(content)).arrayBuffer()) ) return new Blob([iv, key.salt, encrypted]) } catch (e) { console.error('failed to encrypt ' + name + ': ' + e) } } } export function parseStoredString(raw: string): Promise<Blob> { return new Promise(async resolve => { resolve(await fetch('data:application/octet-stream;base64,' + raw.substring(1)).then(res => res.blob())) }) } export async function decrypt(name: string, content: string | Blob, password?: string) { const buffer = await ('string' === typeof content ? (await parseStoredString(content)).arrayBuffer() : content.arrayBuffer()) const key = password ? await getKey(name, password, new Uint8Array(buffer, 12, 16)) : keys[name] Eif (key) { try { const decrypted = await crypto.subtle.decrypt( {name: 'AES-GCM', iv: new Uint8Array(buffer, 0, 12)}, key.key, new Uint8Array(buffer, 28) ) return decompress(new Blob([decrypted])) } catch (e) { console.error('failed to decrypt ' + name + ': ' + e) } } } |