-
Notifications
You must be signed in to change notification settings - Fork 177
/
common.js
67 lines (59 loc) · 3.67 KB
/
common.js
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
// minified version of https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727
const b64 = (function(){"use strict";var b64={},base64abc=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"],base64codes=[255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,62,255,255,255,63,52,53,54,55,56,57,58,59,60,61,255,255,255,0,255,255,255,0,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,255,255,255,255,255,255,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];function getBase64Code(e){if(e>base64codes.length)throw new Error("Unable to parse base64 string.");var a=base64codes[e];if(255===a)throw new Error("Unable to parse base64 string.");return a}function bytesToBase64(e){var a,s="",t=e.length;for(a=2;a<t;a+=3)s+=base64abc[e[a-2]>>2],s+=base64abc[(3&e[a-2])<<4|e[a-1]>>4],s+=base64abc[(15&e[a-1])<<2|e[a]>>6],s+=base64abc[63&e[a]];return a===t+1&&(s+=base64abc[e[a-2]>>2],s+=base64abc[(3&e[a-2])<<4],s+="=="),a===t&&(s+=base64abc[e[a-2]>>2],s+=base64abc[(3&e[a-2])<<4|e[a-1]>>4],s+=base64abc[(15&e[a-1])<<2],s+="="),s}function base64ToBytes(e){if(e.length%4!=0)throw new Error("Unable to parse base64 string.");var a=e.indexOf("=");if(-1!==a&&a<e.length-2)throw new Error("Unable to parse base64 string.");for(var s,t=e.endsWith("==")?2:e.endsWith("=")?1:0,r=e.length,o=new Uint8Array(r/4*3),n=0,b=0;n<r;n+=4,b+=3)s=getBase64Code(e.charCodeAt(n))<<18|getBase64Code(e.charCodeAt(n+1))<<12|getBase64Code(e.charCodeAt(n+2))<<6|getBase64Code(e.charCodeAt(n+3)),o[b]=s>>16,o[b+1]=s>>8&255,o[b+2]=255&s;return o.subarray(0,o.length-t)}function base64encode(e){return bytesToBase64((arguments.length>1&&void 0!==arguments[1]?arguments[1]:new TextEncoder).encode(e))}function base64decode(e){return(arguments.length>1&&void 0!==arguments[1]?arguments[1]:new TextDecoder).decode(base64ToBytes(e))}b64.bytesToBase64=bytesToBase64;b64.base64ToBytes=base64ToBytes;b64.base64encode=base64encode;b64.base64decode=base64decode;return b64})();
async function encrypt(text, b64Key) {
const key = await crypto.subtle.importKey(
"raw",
b64.base64ToBytes(b64Key),
{name: "AES-GCM"},
false,
["encrypt"]
);
const enc = new TextEncoder();
const iv = crypto.getRandomValues(new Uint8Array(12));
const ciphertext = await crypto.subtle.encrypt(
{
name: "AES-GCM",
iv: iv
},
key,
enc.encode(text)
);
const result = new Uint8Array(iv.length + ciphertext.byteLength);
result.set(iv);
result.set(new Uint8Array(ciphertext), iv.length);
return b64.bytesToBase64(result);
}
async function decrypt(encryptedText, b64Key) {
const key = await crypto.subtle.importKey(
"raw",
b64.base64ToBytes(b64Key),
{name: "AES-GCM"},
false,
["decrypt"]
);
const encryptedBytes = b64.base64ToBytes(encryptedText);
const iv = encryptedBytes.slice(0, 12);
const ciphertext = encryptedBytes.slice(12);
const decrypted = await crypto.subtle.decrypt(
{
name: "AES-GCM",
iv: iv
},
key,
ciphertext
);
const dec = new TextDecoder();
return dec.decode(decrypted);
}
async function generateKey() {
const key = await crypto.subtle.generateKey(
{
name: "AES-GCM",
length: 256,
},
true,
["encrypt"] // Chrome doesn't like when it's empty
);
const rawKey = await crypto.subtle.exportKey("raw", key);
return b64.bytesToBase64(new Uint8Array(rawKey));
}