-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcrypto.mjs
104 lines (86 loc) · 3.37 KB
/
crypto.mjs
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// See https://github.com/axetroy/deno_machine_id
//const buff_to_base64 = (buff) => btoa(String.fromCharCode.apply(null, buff));
//const base64_to_buf = (b64) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(null));
import {execCmd} from "./utils/smallUtilFuncs.mjs";
const enc = new TextEncoder();
const dec = new TextDecoder();
async function machineId() {
let guid;
switch (Deno.build.os) {
case "linux": {
var output = "";
try {
output = await execCmd(
["cat", "/var/lib/dbus/machine-id", "/etc/machine-id"],
);
} catch {
output = await execCmd(["hostname"]);
}
guid = output
.substr(0, output.indexOf("\n"))
.replace(/\r+|\n+|\s+/ig, "")
.toLowerCase();
break;
}
case "darwin": {
const output = await execCmd(
["ioreg", "-rd1", "-c", "IOPlatformExpertDevice"],
);
guid = output.split("IOPlatformUUID")[1]
.split("\n")[0].replace(/\=|\s+|\"/ig, "")
.toLowerCase();
break;
}
case "windows": {
const output = await execCmd(
[
"REG",
"QUERY",
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography",
"/v",
"MachineGuid",
],
);
guid = output
.split("REG_SZ")[1]
.replace(/\r+|\n+|\s+/ig, "")
.toLowerCase();
break;
}
}
return guid;
}
const HW_ID = await machineId();
const getPasswordKey = (password) =>
crypto.subtle.importKey("raw", enc.encode(password), "PBKDF2", false, ["deriveKey", "deriveBits"]);
const deriveKey = (passwordKey, salt, keyUsage) =>
crypto.subtle.deriveKey(
{name: "PBKDF2", salt, iterations: 250000, hash: "SHA-256"},
passwordKey, {name: "AES-CBC", length: 256}, false, keyUsage
);
const IV_SIZE = 16;
const SALT_SIZE = 16;
export async function encryptData(secretData, password=HW_ID) {
const salt = crypto.getRandomValues(new Uint8Array(SALT_SIZE));
const iv = crypto.getRandomValues(new Uint8Array(IV_SIZE));
const passwordKey = await getPasswordKey(password);
const aesKey = await deriveKey(passwordKey, salt, ["encrypt"]);
const encryptedContent = await crypto.subtle.encrypt({name: "AES-CBC", iv}, aesKey, enc.encode(secretData));
const encryptedContentArr = new Uint8Array(encryptedContent);
let buff = new Uint8Array(
salt.byteLength + iv.byteLength + encryptedContentArr.byteLength
);
buff.set(salt, 0);
buff.set(iv, salt.byteLength);
buff.set(encryptedContentArr, salt.byteLength + iv.byteLength);
return buff;
}
export async function decryptData(encryptedDataBuff, password=HW_ID) {
const salt = encryptedDataBuff.slice(0, SALT_SIZE);
const iv = encryptedDataBuff.slice(SALT_SIZE, SALT_SIZE + IV_SIZE);
const data = encryptedDataBuff.slice(SALT_SIZE + IV_SIZE);
const passwordKey = await getPasswordKey(password);
const aesKey = await deriveKey(passwordKey, salt, ["decrypt"]);
const decryptedContent = await crypto.subtle.decrypt({name: "AES-CBC", iv}, aesKey, data);
return dec.decode(decryptedContent);
}