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 | 20x 20x 7x 7x 7x 7x 13x 13x 13x 13x 13x 13x 2x 2x 3x 3x 3x 3x 3x 3x | import {compress, decompress} from './compression'
type StoredKey = {salt: Uint8Array<ArrayBuffer>; key: CryptoKey}
export const keys: {[index: string]: StoredKey} = {}
const encoder = new TextEncoder()
async function getKey(name: string, password: string, salt: Uint8Array<ArrayBuffer>): 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',
hash: 'SHA-256',
salt,
iterations: 1e6,
} as Pbkdf2Params,
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)
}
}
}
|