1 | /* global sjcl */ |
||
2 | |||
3 | window.OTP = (function () { |
||
4 | function dec2hex(s) { |
||
5 | return (s < 15.5 ? '0' : '') + Math.round(s).toString(16); |
||
6 | } |
||
7 | |||
8 | function hex2dec(s) { |
||
9 | return parseInt(s, 16); |
||
10 | } |
||
11 | |||
12 | function base32tohex(base32) { |
||
13 | if (!base32) { |
||
14 | return; |
||
15 | } |
||
16 | var base32chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; |
||
17 | var bits = ""; |
||
18 | var hex = ""; |
||
19 | var i; |
||
20 | for (i = 0; i < base32.length; i++) { |
||
21 | var val = base32chars.indexOf(base32.charAt(i).toUpperCase()); |
||
22 | bits += leftpad(val.toString(2), 5, '0'); |
||
23 | } |
||
24 | |||
25 | for (i = 0; i + 4 <= bits.length; i += 4) { |
||
26 | var chunk = bits.substr(i, 4); |
||
27 | hex = hex + parseInt(chunk, 2).toString(16); |
||
28 | } |
||
29 | return hex; |
||
30 | |||
31 | } |
||
32 | |||
33 | function leftpad(str, len, pad) { |
||
34 | if (len + 1 >= str.length) { |
||
35 | str = Array(len + 1 - str.length).join(pad) + str; |
||
36 | } |
||
37 | return str; |
||
38 | } |
||
39 | |||
40 | |||
41 | var _OTP = { |
||
42 | secret: '', |
||
43 | getOTP: function () { |
||
44 | if (!this.secret) { |
||
45 | return; |
||
46 | } |
||
47 | var key = base32tohex(this.secret); |
||
48 | var epoch = Math.round(new Date().getTime() / 1000.0); |
||
49 | var time = leftpad(dec2hex(Math.floor(epoch / 30)), 16, '0'); |
||
50 | /** global: jsSHA */ |
||
51 | var hmacObj = new jsSHA(time, 'HEX'); |
||
0 ignored issues
–
show
Coding Style
Best Practice
introduced
by
Loading history...
|
|||
52 | var hmac = hmacObj.getHMAC(key, 'HEX', 'SHA-1', "HEX"); |
||
53 | var offset = hex2dec(hmac.substring(hmac.length - 1)); |
||
54 | var otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + ''; |
||
55 | otp = (otp).substr(otp.length - 6, 6); |
||
56 | return otp; |
||
57 | } |
||
58 | }; |
||
59 | return _OTP; |
||
60 | }()); |