Created
November 2, 2021 02:28
-
-
Save Explosion-Scratch/cc7b4816967c17af65169df8baf473dd to your computer and use it in GitHub Desktop.
Generates an authenticator token based on a secret key. (Usually given in the QR code that apps have you scan)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function getToken(key, options) { | |
let { default: JsSHA } = await import( | |
"https://cdn.skypack.dev/pin/[email protected]/mode=imports,min/optimized/jssha.js" | |
); | |
options = { | |
period: 30, | |
algorithm: "SHA-1", | |
digits: 6, | |
timestamp: Date.now(), | |
...options, | |
}; | |
key = base32tohex(key); | |
let epoch = Math.round(options.timestamp / 1000.0); | |
let time = leftpad(dec2hex(Math.floor(epoch / options.period)), 16, "0"); | |
let shaObj = new JsSHA(options.algorithm, "HEX"); | |
shaObj.setHMACKey(key, "HEX"); | |
shaObj.update(time); | |
let hmac = shaObj.getHMAC("HEX"); | |
let offset = hex2dec(hmac.substring(hmac.length - 1)); | |
let otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec("7fffffff")) + ""; | |
otp = otp.substr(Math.max(otp.length - options.digits, 0), options.digits); | |
return otp; | |
function hex2dec(s) { | |
return parseInt(s, 16); | |
} | |
function dec2hex(s) { | |
return (s < 15.5 ? "0" : "") + Math.round(s).toString(16); | |
} | |
function base32tohex(base32) { | |
let base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", | |
bits = "", | |
hex = ""; | |
base32 = base32.replace(/=+$/, ""); | |
for (let i = 0; i < base32.length; i++) { | |
let val = base32chars.indexOf(base32.charAt(i).toUpperCase()); | |
if (val === -1) throw new Error("Invalid base32 character in key"); | |
bits += leftpad(val.toString(2), 5, "0"); | |
} | |
for (let i = 0; i + 8 <= bits.length; i += 8) { | |
let chunk = bits.substr(i, 8); | |
hex = hex + leftpad(parseInt(chunk, 2).toString(16), 2, "0"); | |
} | |
return hex; | |
} | |
function leftpad(str, len, pad) { | |
if (len + 1 >= str.length) { | |
str = Array(len + 1 - str.length).join(pad) + str; | |
} | |
return str; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment