1//
2// Cryptography
3// \ (•◡•) /
4//
5// Data encryption & decryption.
6
7
8import * as Uint8arrays from "uint8arrays"
9
10
11const extractable = false
12
13
14export async function keyFromPassphrase(passphrase: string): Promise<CryptoKey> {
15 const baseKey = await crypto.subtle.importKey(
16 "raw",
17 Uint8arrays.fromString(passphrase, "utf8"),
18 {
19 name: "PBKDF2"
20 },
21 false,
22 [ "deriveKey" ]
23 )
24
25 return await crypto.subtle.deriveKey(
26 {
27 name: "PBKDF2",
28 salt: Uint8arrays.fromString("diffuse", "utf8"),
29 iterations: 10000,
30 hash: "SHA-512"
31 },
32 baseKey,
33 {
34 name: "AES-GCM",
35 length: 256
36 },
37 extractable,
38 [ "encrypt", "decrypt" ]
39 )
40}
41
42
43export async function encrypt(key: CryptoKey, string: string): Promise<string> {
44 const iv = crypto.getRandomValues(new Uint8Array(12))
45
46 const buf = await crypto.subtle.encrypt(
47 {
48 name: "AES-GCM",
49 iv: iv,
50 tagLength: 128
51 },
52 key,
53 Uint8arrays.fromString(string, "utf8")
54 )
55
56 const iv_b64 = Uint8arrays.toString(iv, "base64pad")
57 const buf_b64 = Uint8arrays.toString(new Uint8Array(buf), "base64pad")
58 return iv_b64 + buf_b64
59}
60
61
62export async function decrypt(key: CryptoKey, string: string): Promise<string> {
63 const iv_b64 = string.substring(0, 16)
64 const buf_b64 = string.substring(16)
65
66 const iv = Uint8arrays.fromString(iv_b64, "base64pad")
67 const buf = Uint8arrays.fromString(buf_b64, "base64pad")
68
69 const decrypted = await crypto.subtle.decrypt(
70 {
71 name: "AES-GCM",
72 iv: iv,
73 tagLength: 128
74 },
75 key,
76 buf
77 )
78
79 return Uint8arrays.toString(
80 new Uint8Array(decrypted),
81 "utf8"
82 )
83}