Skip to content

Instantly share code, notes, and snippets.

@gbraad
Last active September 7, 2023 11:57
Show Gist options
  • Save gbraad/2885828 to your computer and use it in GitHub Desktop.
Save gbraad/2885828 to your computer and use it in GitHub Desktop.
The core algorithm/TOTP implementation used by GAuth: http://github.com/gbraad/gauth/, https://gauth.apps.gbraad.nl
// http://blog.tinisles.com/2011/10/google-authenticator-one-time-password-algorithm-in-javascript/
function dec2hex(s) {
return (s < 15.5 ? '0' : '') + Math.round(s).toString(16);
}
function hex2dec(s) {
return parseInt(s, 16);
}
function base32tohex(base32) {
var base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
var bits = "";
var hex = "";
for (var i = 0; i < base32.length; i++) {
var val = base32chars.indexOf(base32.charAt(i).toUpperCase());
bits += leftpad(val.toString(2), 5, '0');
}
for (var i = 0; i+4 <= bits.length; i+=4) {
var chunk = bits.substr(i, 4);
hex = hex + parseInt(chunk, 2).toString(16) ;
}
return hex;
}
function leftpad(str, len, pad) {
if (len + 1 >= str.length) {
str = Array(len + 1 - str.length).join(pad) + str;
}
return str;
}
function updateOtp(secret) {
var key = base32tohex(secret);
var epoch = Math.round(new Date().getTime() / 1000.0);
var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0');
var hmacObj = new jsSHA(time, 'HEX');
var hmac = hmacObj.getHMAC(key, 'HEX', 'SHA-1', "HEX");
//qrImg = https://chart.googleapis.com/chart?chs=200x200&cht=qr&chl=200x200&chld=M|0&cht=qr&chl=otpauth://totp/' + account + '3Fsecret%3D' + secret;
//var keyLength = (key.length * 4);
var offset = hex2dec(hmac.substring(hmac.length - 1));
//var part1 = hmac.substr(0, offset * 2);
//var part2 = hmac.substr(offset * 2, 8);
//var part3 = hmac.substr(offset * 2 + 8, hmac.length - offset);
var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
return (otp).substr(otp.length - 6, 6);
}
function timer() {
var epoch = Math.round(new Date().getTime() / 1000.0);
var countDown = 30 - (epoch % 30);
if (epoch % 30 == 0) {
updateOtp("JBSWY3DPEHPK3PXP");
}
return countDown;
}
@berdosi
Copy link

berdosi commented Mar 16, 2020

With recent jsSHA that's how I got it to work:

    var hmacObj = new jsSHA('SHA-1', 'HEX');
    hmacObj.setHMACKey(key, 'HEX');
    hmacObj.update(time);
    var hmac = hmacObj.getHMAC('HEX', 'SHA-1', "HEX");

I know this is some serious necrothreading, but this is still the best TOTP code I found for JavaScript. :)

@Zibri
Copy link

Zibri commented Sep 4, 2023

how about to make it work in nodejs without jsSHA but using the native module crypto ?

@gbraad
Copy link
Author

gbraad commented Sep 4, 2023

Patches are welcome. This hasn't seen modifications since 2012, and is still used this way in gauth (From the browser). Compatibility is key...

@Zibri
Copy link

Zibri commented Sep 5, 2023

Patches are welcome. This hasn't seen modifications since 2012, and is still used this way in gauth (From the browser). Compatibility is key...

I think you mean https://chrome.google.com/webstore/detail/gauth-authenticator/ilgcnhelpchnceeipipijaljkblbcobl
But that's from you not from google :D

@gbraad
Copy link
Author

gbraad commented Sep 7, 2023

Link is in the gist.

I think you mean https://chrome.google.com/webstore/detail/gauth-authenticator/ilgcnhelpchnceeipipijaljkblbcobl

Yes, that is actually my extension. I suggest you to read more carefully, as the gist says this is the core of the GAuth tool.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment