I recently released an iOS and Android application called OTP Safe to iTunes and Google Play. OTP Safe makes use of the time-based one-time password (TOTP) algorithm commonly used with two-factor authentication (2FA). How exactly, does this algorithm work, and how can we make it work with JavaScript?
Using the following resources as our framework, we can make use of the TOTP algorithm quickly and easily:
For TOTP to work, we are going to need to make use of an HMAC function. JavaScript doesn’t natively have one, but lucky for us there is a great open source library called jsSHA that we can use.
A little background on two-factor authentication and time-based one-time passwords in general. Two-factor authentication is an extra layer of security that many web services offer. You enter your normal username and password followed by a six digit code that changes every thirty seconds. This six digit code is determined based on a secret key that both you and the web service share. The code changes based on the machines system time so it is important the web service and device have accurate times configured.
A complete and working version of my code can be seen below:
TOTP = function() {
var dec2hex = function(s) {
return (s < 15.5 ? "0" : "") + Math.round(s).toString(16);
};
var hex2dec = function(s) {
return parseInt(s, 16);
};
var leftpad = function(s, l, p) {
if(l + 1 >= s.length) {
s = Array(l + 1 - s.length).join(p) + s;
}
return s;
};
var base32tohex = function(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;
};
this.getOTP = function(secret) {
try {
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(base32tohex(secret), "HEX", "SHA-1", "HEX");
var offset = hex2dec(hmac.substring(hmac.length - 1));
var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec("7fffffff")) + "";
otp = (otp).substr(otp.length - 6, 6);
} catch (error) {
throw error;
}
return otp;
};
}
The above TOTP code can be used like the following:
var totpObj = new TOTP();
var otp = totpObj.getOTP("SECRET_HERE");
Don’t forget that you will need to include these libraries in your HTML file like so:
<html>
<head>
<script src="sha.js"></script>
<script src="totp.js"></script>
</head>
<body>
</body>
</html>
Just like that, you now have a perfectly capable way to generate six digit passwords for two-factor services. You can even use this code, like I did, in your JavaScript based Phonegap or Ionic Framework application.