Created
June 18, 2015 05:11
-
-
Save composite/79766b23ec435b2dd696 to your computer and use it in GitHub Desktop.
a Simple TOTP impl with js
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
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>TOTP Simple Example</title> | |
| </head> | |
| <body> | |
| <h3>OTP</h3> | |
| <input type="text" id="otp" readonly=""> | |
| <h3>REMAIN</h3> | |
| <input type="text" id="sec" readonly=""> | |
| <script type="text/javascript"> | |
| //https://blog.nraboy.com/2014/10/generate-time-based-one-time-passwords-javascript/ | |
| var 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 shaObj = new jsSHA("SHA-1", "TEXT"); | |
| shaObj.setHMACKey(base32tohex(secret), "HEX"); | |
| shaObj.update(time, "HEX"); | |
| var hmac = shaObj.getHMAC("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; | |
| }; | |
| }; | |
| </script> | |
| <script type="text/javascript"> | |
| //https://gist.github.com/manast/1185904 | |
| //https://gist.github.com/tanepiper/4215634 | |
| var HighResolutionTimer = window.HighResolutionTimer = window.HighResolutionTimer || (function() { | |
| var HighResolutionTimer = function(options) { | |
| this.timer = false; | |
| this.total_ticks = 0; | |
| this.start_time = undefined; | |
| this.current_time = undefined; | |
| this.duration = (options.duration) ? options.duration : 1000; | |
| this.callback = (options.callback) ? options.callback : function() {}; | |
| this.run = function() { | |
| this.current_time = Date.now(); | |
| if (!this.start_time) { | |
| this.start_time = this.current_time; | |
| } | |
| this.callback(this); | |
| var nextTick = this.duration - (this.current_time - (this.start_time + (this.total_ticks * this.duration))); | |
| this.total_ticks++; | |
| (function(i) { | |
| i.timer = setTimeout(function() { | |
| i.run(); | |
| }, nextTick); | |
| }(this)); | |
| return this; | |
| }; | |
| this.stop = function() { | |
| clearTimeout(this.timer); | |
| return this; | |
| }; | |
| return this; | |
| }; | |
| return HighResolutionTimer; | |
| }()); | |
| </script> | |
| <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.0.0/sha.js"></script> | |
| <script type="text/javascript"> | |
| var once = true; | |
| var _timer = HighResolutionTimer({ | |
| duration: 1000, | |
| callback: function(timer) { | |
| var seconds = Math.round(new Date().getTime() / 1000.0) % 30; | |
| if (!seconds || once) { | |
| var otp = new TOTP().getOTP("JBSWY3DPEHPK3PXP");//INSERT YOUR SECRET HERE | |
| document.getElementById('otp').value = otp; | |
| once = false; | |
| } | |
| document.getElementById('sec').value = (30 - seconds) + ' sec(s)'; | |
| } | |
| }).run(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment