-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
93 lines (82 loc) · 2.86 KB
/
index.js
File metadata and controls
93 lines (82 loc) · 2.86 KB
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
const { createHmac } = require("crypto");
const { existsSync, readFileSync } = require("fs");
const { exit } = require("process");
const clipboardy = require("clipboardy");
const base32Decode = require("base32-decode");
const ntpClient = require("ntp-client");
(async () => {
let errorMessage = null;
let secret = null;
if (existsSync("secret.raw")) {
secret = readFileSync("secret.raw");
if (secret.length !== 20) {
errorMessage = "Secret key should be 20 bytes!";
}
} else if (existsSync("secret.base64")) {
const base64String = readFileSync("secret.base64", "utf8").trim();
if (/^[A-Za-z0-9+/]{27}=?$/.test(base64String)) {
secret = Buffer.from(base64String, "base64");
} else {
errorMessage = "Secret key should be 27 base-64 digits!";
}
} else if (existsSync("secret.base32")) {
const base32String = readFileSync("secret.base32", "utf8").trim();
if (/^[A-Za-z2-7]{32}$/.test(base32String)) {
secret = Buffer.from(base32Decode(base32String, "RFC4648"));
} else {
errorMessage = "Secret key should be 32 base-32 digits!";
}
} else if (existsSync("secret.hex")) {
const hexString = readFileSync("secret.hex", "utf8").trim();
if (/^[0-9a-fA-F]{40}$/.test(hexString)) {
secret = Buffer.from(hexString, "hex");
} else {
errorMessage = "Secret key should be 40 hex digits!";
}
} else {
errorMessage =
"Please create a 'secret' file (secret.hex OR secret.base32 OR secret.raw)";
}
if (errorMessage) {
console.error(errorMessage);
setTimeout(() => exit(1), 5000);
} else {
// initialize hmac of secret key
const hmac = createHmac("sha1", secret);
// get current time
let time = new Date();
try {
time = await new Promise((resolve, reject) =>
ntpClient.getNetworkTime("pool.ntp.org", 123, (err, date) =>
err ? reject(err) : resolve(date)
)
);
console.log("Set time via ntp.org");
} catch (e1) {
console.error("Error fetching time via ntp.org:", e1);
try {
const response = await fetch("https://www.google.com/");
time = new Date(response.headers.get("date"));
console.log("Set time via google.com");
} catch (e2) {
console.error("Error fetching time via google.com:", e2);
setTimeout(() => exit(1), 5000);
}
}
// calculate number of 30-second intervals since 1970-01-01
const c = Buffer.alloc(8);
c.writeBigInt64BE(BigInt(time.getTime()) / 30000n);
// digest the payload
hmac.update(c);
// get hmac output
const buf = hmac.digest();
// the offset is the last 4 bits of the output
const offset = buf.readUInt8(19) & 0xf;
// get the integer result
const n = buf.readUInt32BE(offset) & 0x7fffffff;
// get the last 6 digits of integer result
const sixDigits = (n % 1000000).toString().padStart(6, "0");
// copy to clipboard
clipboardy.writeSync(sixDigits);
}
})();