blob: 0bc3feaf820fc82f7cc6a77a252e11b9331527d0 (
plain)
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
|
/* eslint-disable @typescript-eslint/camelcase */
import jssha from 'jssha'
const SEARCH_RANGE = 16
const timeStep = 30
export function computeTOTPandCheck(secretKey: Uint8Array, digits: number, code: number): boolean {
const now = new Date().getTime()
const epoch = Math.floor(Math.round(now / 1000.0) / timeStep);
for (let ms = -SEARCH_RANGE; ms < SEARCH_RANGE; ms++) {
const movingFactor = (epoch + ms).toString(16).padStart(16, "0");
const hmacSha = new jssha('SHA-1', 'HEX', { hmacKey: { value: secretKey, format: 'UINT8ARRAY' } });
hmacSha.update(movingFactor);
const hmac_text = hmacSha.getHMAC('UINT8ARRAY');
const offset = (hmac_text[hmac_text.length - 1] & 0xf)
const otp = ((
(hmac_text[offset + 0] << 24) +
(hmac_text[offset + 1] << 16) +
(hmac_text[offset + 2] << 8) +
(hmac_text[offset + 3])
) & 0x7fffffff) % Math.pow(10, digits)
if (otp == code) return true
}
return false
}
const encTable__ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".split('')
export function base32enc(buffer: Uint8Array): string {
let rpos = 0
let bits = 0
let vbit = 0
let result = ""
while ((rpos < buffer.length) || (vbit > 0)) {
if ((rpos < buffer.length) && (vbit < 5)) {
bits = (bits << 8) | buffer[rpos++];
vbit += 8;
}
if (vbit < 5) {
bits <<= (5 - vbit);
vbit = 5;
}
result += encTable__[(bits >> (vbit - 5)) & 31];
vbit -= 5;
}
return result
}
// const array = new Uint8Array(256)
// const secretKey = window.crypto.getRandomValues(array)
// console.log(base32enc(secretKey))
|