rotp 4.0.0 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +19 -0
  3. data/.devcontainer/devcontainer.json +41 -0
  4. data/.github/workflows/release.yaml +36 -0
  5. data/.github/workflows/test.yaml +26 -0
  6. data/.release-please-manifest.json +3 -0
  7. data/CHANGELOG.md +91 -24
  8. data/Dockerfile-2.3 +1 -7
  9. data/Dockerfile-2.7 +11 -0
  10. data/Dockerfile-3.0 +12 -0
  11. data/Guardfile +1 -1
  12. data/README.md +64 -15
  13. data/bin/rotp +1 -1
  14. data/docker-compose.yml +37 -0
  15. data/lib/rotp/arguments.rb +6 -5
  16. data/lib/rotp/base32.rb +56 -30
  17. data/lib/rotp/cli.rb +4 -5
  18. data/lib/rotp/hotp.rb +6 -13
  19. data/lib/rotp/otp/uri.rb +78 -0
  20. data/lib/rotp/otp.rb +26 -25
  21. data/lib/rotp/totp.rb +13 -33
  22. data/lib/rotp/version.rb +1 -1
  23. data/lib/rotp.rb +2 -4
  24. data/release-please-config.json +12 -0
  25. data/rotp.gemspec +13 -15
  26. data/spec/lib/rotp/arguments_spec.rb +5 -6
  27. data/spec/lib/rotp/base32_spec.rb +45 -19
  28. data/spec/lib/rotp/cli_spec.rb +21 -6
  29. data/spec/lib/rotp/hotp_spec.rb +38 -17
  30. data/spec/lib/rotp/otp/uri_spec.rb +99 -0
  31. data/spec/lib/rotp/totp_spec.rb +61 -98
  32. data/spec/spec_helper.rb +1 -2
  33. metadata +25 -43
  34. data/.travis.yml +0 -8
  35. data/Dockerfile-1.9 +0 -15
  36. data/Dockerfile-2.1 +0 -16
  37. data/Rakefile +0 -9
  38. data/doc/ROTP/HOTP.html +0 -308
  39. data/doc/ROTP/OTP.html +0 -593
  40. data/doc/ROTP/TOTP.html +0 -493
  41. data/doc/Rotp.html +0 -179
  42. data/doc/_index.html +0 -144
  43. data/doc/class_list.html +0 -36
  44. data/doc/css/common.css +0 -1
  45. data/doc/css/full_list.css +0 -53
  46. data/doc/css/style.css +0 -310
  47. data/doc/file.README.html +0 -89
  48. data/doc/file_list.html +0 -38
  49. data/doc/frames.html +0 -13
  50. data/doc/index.html +0 -89
  51. data/doc/js/app.js +0 -203
  52. data/doc/js/full_list.js +0 -149
  53. data/doc/js/jquery.js +0 -154
  54. data/doc/method_list.html +0 -155
  55. data/doc/top-level-namespace.html +0 -88
data/doc/file_list.html DELETED
@@ -1,38 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html>
4
- <head>
5
- <meta name="Content-Type" content="text/html; charset=utf-8" />
6
- <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
7
- <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
8
- <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
9
- <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
10
- <base id="base_target" target="_parent" />
11
- </head>
12
- <body>
13
- <script type="text/javascript" charset="utf-8">
14
- if (window.top.frames.main) {
15
- document.getElementById('base_target').target = 'main';
16
- document.body.className = 'frames';
17
- }
18
- </script>
19
- <div id="content">
20
- <h1 id="full_list_header">File List</h1>
21
- <div id="nav">
22
- <a target="_self" href="class_list.html">Classes</a> |
23
- <a target="_self" href="method_list.html">Methods</a> |
24
- <a target="_self" href="file_list.html">Files</a>
25
- </div>
26
- <div id="search">Search: <input type="text" /></div>
27
-
28
- <ul id="full_list" class="files">
29
-
30
-
31
- <li class="r1"><a href="index.html" title="README">README</a></li>
32
-
33
-
34
- </ul>
35
- </div>
36
- </body>
37
- </html>
38
-
data/doc/frames.html DELETED
@@ -1,13 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
3
-
4
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
- <head>
6
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
- <title>Documentation by YARD 0.6.4</title>
8
- </head>
9
- <frameset cols="20%,*">
10
- <frame name="list" src="class_list.html" />
11
- <frame name="main" src="index.html" />
12
- </frameset>
13
- </html>
data/doc/index.html DELETED
@@ -1,89 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
- <head>
5
- <meta name="Content-Type" content="text/html; charset=utf-8" />
6
- <title>Documentation by YARD 0.6.4</title>
7
- <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
8
- <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
9
-
10
- <script type="text/javascript" charset="utf-8">
11
- relpath = '';
12
- if (relpath != '') relpath += '/';
13
- </script>
14
- <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
15
- <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
16
-
17
- </head>
18
- <body>
19
- <script type="text/javascript" charset="utf-8">
20
- if (window.top.frames.main) document.body.className = 'frames';
21
- </script>
22
-
23
- <div id="header">
24
- <div id="menu">
25
-
26
- <a href="_index.html" title="Index">Index</a> &raquo;
27
- <span class="title">File: README</span>
28
-
29
-
30
- <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
31
- </div>
32
-
33
- <div id="search">
34
- <a id="class_list_link" href="#">Class List</a>
35
- <a id="method_list_link" href="#">Method List</a>
36
- <a id ="file_list_link" href="#">File List</a>
37
- </div>
38
-
39
- <div class="clear"></div>
40
- </div>
41
-
42
- <iframe id="search_frame"></iframe>
43
-
44
- <div id="content"><div id='filecontents'><h1 id='rotp__the_ruby_one_time_password_library'>ROTP - The Ruby One Time Password Library</h1>
45
-
46
- <h3 id='installation'>Installation</h3>
47
-
48
- <pre class="code"><span class='gem identifier id'>gem</span> <span class='install identifier id'>install</span> <span class='rotp identifier id'>rotp</span>
49
- </pre>
50
-
51
- <h3 id='use'>Use</h3>
52
-
53
- <h4 id='time_based_otps'>Time based OTP&#8217;s</h4>
54
-
55
- <pre class="code"><span class='totp identifier id'>totp</span> <span class='assign token'>=</span> <span class='ROTP constant id'>ROTP</span><span class='colon2 op'>::</span><span class='TOTP constant id'>TOTP</span><span class='dot token'>.</span><span class='new identifier id'>new</span><span class='lparen token'>(</span><span class='string val'>&quot;base32secretkey&quot;</span><span class='rparen token'>)</span>
56
- <span class='totp identifier id'>totp</span><span class='dot token'>.</span><span class='now identifier id'>now</span> <span class='comment val'># =&gt; 492039</span>
57
- <span class='totp identifier id'>totp</span><span class='dot token'>.</span><span class='at identifier id'>at</span><span class='lparen token'>(</span><span class='Time constant id'>Time</span><span class='dot token'>.</span><span class='now identifier id'>now</span><span class='dot token'>.</span><span class='to_i identifier id'>to_i</span> <span class='plus op'>+</span> <span class='integer val'>30</span><span class='rparen token'>)</span> <span class='comment val'># =&gt; 102922</span>
58
- </pre>
59
-
60
- <h4 id='counter_based_otps'>Counter based OTP&#8217;s</h4>
61
-
62
- <pre class="code"><span class='hotp identifier id'>hotp</span> <span class='assign token'>=</span> <span class='ROTP constant id'>ROTP</span><span class='colon2 op'>::</span><span class='HOTP constant id'>HOTP</span><span class='dot token'>.</span><span class='new identifier id'>new</span><span class='lparen token'>(</span><span class='string val'>&quot;base32secretkey&quot;</span><span class='rparen token'>)</span>
63
- <span class='hotp identifier id'>hotp</span><span class='dot token'>.</span><span class='at identifier id'>at</span><span class='lparen token'>(</span><span class='integer val'>0</span><span class='rparen token'>)</span> <span class='comment val'># =&gt; 492039</span>
64
- <span class='hotp identifier id'>hotp</span><span class='dot token'>.</span><span class='at identifier id'>at</span><span class='lparen token'>(</span><span class='integer val'>1</span><span class='rparen token'>)</span> <span class='comment val'># =&gt; 234092</span>
65
- <span class='hotp identifier id'>hotp</span><span class='dot token'>.</span><span class='at identifier id'>at</span><span class='lparen token'>(</span><span class='integer val'>2</span><span class='rparen token'>)</span> <span class='comment val'># =&gt; 209834</span>
66
- </pre>
67
-
68
- <h4 id='generating_a_base32_secret_key'>Generating a Base32 Secret key</h4>
69
-
70
- <pre class="code"><span class='ROTP constant id'>ROTP</span><span class='dot token'>.</span><span class='random_base32 identifier id'>random_base32</span> <span class='comment val'># returns a 16 character base32 secret. Compatible with Google Authenticator</span>
71
- </pre>
72
-
73
- <h4 id='google_authenticator_interop'>Google Authenticator Interop</h4>
74
-
75
- <p>The library works with the Google Authenticator iPhone and Android app, and also includes the ability to generate provisioning URI&#8217;s for use with the QR Code scanner built into the app.</p>
76
-
77
- <pre class="code"><span class='hotp identifier id'>hotp</span><span class='dot token'>.</span><span class='provisioning_uri identifier id'>provisioning_uri</span> <span class='comment val'># =&gt; 'otpauth://totp/alice@google.com?secret=JBSWY3DPEHPK3PXP'</span>
78
- </pre>
79
-
80
- <p>This can then be rendered as a QR Code which can then be scanned and added to the users list of OTP credentials.</p></div></div>
81
-
82
- <div id="footer">
83
- Generated on Sun Feb 13 12:31:40 2011 by
84
- <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
85
- 0.6.4 (ruby-1.8.7).
86
- </div>
87
-
88
- </body>
89
- </html>
data/doc/js/app.js DELETED
@@ -1,203 +0,0 @@
1
- function createSourceLinks() {
2
- $('.method_details_list .source_code').
3
- before("<span class='showSource'>[<a href='#' class='toggleSource'>View source</a>]</span>");
4
- $('.toggleSource').toggle(function() {
5
- $(this).parent().next().slideDown(100);
6
- $(this).text("Hide source");
7
- },
8
- function() {
9
- $(this).parent().next().slideUp(100);
10
- $(this).text("View source");
11
- });
12
- }
13
-
14
- function createDefineLinks() {
15
- var tHeight = 0;
16
- $('.defines').after(" <a href='#' class='toggleDefines'>more...</a>");
17
- $('.toggleDefines').toggle(function() {
18
- tHeight = $(this).parent().prev().height();
19
- $(this).prev().show();
20
- $(this).parent().prev().height($(this).parent().height());
21
- $(this).text("(less)");
22
- },
23
- function() {
24
- $(this).prev().hide();
25
- $(this).parent().prev().height(tHeight);
26
- $(this).text("more...")
27
- });
28
- }
29
-
30
- function createFullTreeLinks() {
31
- var tHeight = 0;
32
- $('.inheritanceTree').toggle(function() {
33
- tHeight = $(this).parent().prev().height();
34
- $(this).parent().toggleClass('showAll');
35
- $(this).text("(hide)");
36
- $(this).parent().prev().height($(this).parent().height());
37
- },
38
- function() {
39
- $(this).parent().toggleClass('showAll');
40
- $(this).parent().prev().height(tHeight);
41
- $(this).text("show all")
42
- });
43
- }
44
-
45
- function fixBoxInfoHeights() {
46
- $('dl.box dd.r1, dl.box dd.r2').each(function() {
47
- $(this).prev().height($(this).height());
48
- });
49
- }
50
-
51
- function searchFrameLinks() {
52
- $('#method_list_link').click(function() {
53
- toggleSearchFrame(this, relpath + 'method_list.html');
54
- });
55
-
56
- $('#class_list_link').click(function() {
57
- toggleSearchFrame(this, relpath + 'class_list.html');
58
- });
59
-
60
- $('#file_list_link').click(function() {
61
- toggleSearchFrame(this, relpath + 'file_list.html');
62
- });
63
- }
64
-
65
- function toggleSearchFrame(id, link) {
66
- var frame = $('#search_frame');
67
- $('#search a').removeClass('active').addClass('inactive');
68
- if (frame.attr('src') == link && frame.css('display') != "none") {
69
- frame.slideUp(100);
70
- $('#search a').removeClass('active inactive');
71
- }
72
- else {
73
- $(id).addClass('active').removeClass('inactive');
74
- frame.attr('src', link).slideDown(100);
75
- }
76
- }
77
-
78
- function linkSummaries() {
79
- $('.summary_signature').click(function() {
80
- document.location = $(this).find('a').attr('href');
81
- });
82
- }
83
-
84
- function framesInit() {
85
- if (window.top.frames.main) {
86
- document.body.className = 'frames';
87
- $('#menu .noframes a').attr('href', document.location);
88
- $('html head title', window.parent.document).text($('html head title').text());
89
- }
90
- }
91
-
92
- function keyboardShortcuts() {
93
- if (window.top.frames.main) return;
94
- $(document).keypress(function(evt) {
95
- if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
96
- if (typeof evt.orignalTarget !== "undefined" &&
97
- (evt.originalTarget.nodeName == "INPUT" ||
98
- evt.originalTarget.nodeName == "TEXTAREA")) return;
99
- switch (evt.charCode) {
100
- case 67: case 99: $('#class_list_link').click(); break; // 'c'
101
- case 77: case 109: $('#method_list_link').click(); break; // 'm'
102
- case 70: case 102: $('#file_list_link').click(); break; // 'f'
103
- }
104
- });
105
- }
106
-
107
- function summaryToggle() {
108
- $('.summary_toggle').click(function() {
109
- localStorage.summaryCollapsed = $(this).text();
110
- $(this).text($(this).text() == "collapse" ? "expand" : "collapse");
111
- var next = $(this).parent().parent().next();
112
- if (next.hasClass('compact')) {
113
- next.toggle();
114
- next.next().toggle();
115
- }
116
- else if (next.hasClass('summary')) {
117
- var list = $('<ul class="summary compact" />');
118
- list.html(next.html());
119
- list.find('.summary_desc, .note').remove();
120
- list.find('a').each(function() {
121
- $(this).html($(this).find('strong').html());
122
- $(this).parent().html($(this)[0].outerHTML);
123
- });
124
- next.before(list);
125
- next.toggle();
126
- }
127
- return false;
128
- });
129
- if (localStorage) {
130
- if (localStorage.summaryCollapsed == "collapse") $('.summary_toggle').click();
131
- else localStorage.summaryCollapsed = "expand";
132
- }
133
- }
134
-
135
- function fixOutsideWorldLinks() {
136
- $('a').each(function() {
137
- if (window.location.host != this.host) this.target = '_parent';
138
- });
139
- }
140
-
141
- function generateTOC() {
142
- if ($('#filecontents').length == 0) return;
143
- var _toc = $('<ol class="top"></ol>');
144
- var show = false;
145
- var toc = _toc;
146
- var counter = 0;
147
- var tags = ['h2', 'h3', 'h4', 'h5', 'h6'];
148
- if ($('#filecontents h1').length > 1) tags.unshift('h1');
149
- for (i in tags) { tags[i] = '#filecontents ' + tags[i] }
150
- var lastTag = parseInt(tags[0][1]);
151
- $(tags.join(', ')).each(function() {
152
- if (this.id == "filecontents") return;
153
- show = true;
154
- var thisTag = parseInt(this.tagName[1]);
155
- if (this.id.length == 0) {
156
- var proposedId = $(this).text().replace(/[^a-z0-9:\.()=-]/ig, '_');
157
- if ($('#' + proposedId).length > 0) proposedId += counter++;
158
- this.id = proposedId;
159
- }
160
- if (thisTag > lastTag) {
161
- for (var i = 0; i < thisTag - lastTag; i++) {
162
- var tmp = $('<ol/>'); toc.append(tmp); toc = tmp;
163
- }
164
- }
165
- if (thisTag < lastTag) {
166
- for (var i = 0; i < lastTag - thisTag; i++) toc = toc.parent();
167
- }
168
- toc.append('<li><a href="#' + this.id + '">' + $(this).text() + '</a></li>');
169
- lastTag = thisTag;
170
- });
171
- if (!show) return;
172
- html = '<div id="toc"><p class="title"><a class="hide_toc" href="#"><strong>Table of Contents</strong></a> <small>(<a href="#" class="float_toc">left</a>)</small></p></div>';
173
- $('#content').prepend(html);
174
- $('#toc').append(_toc);
175
- $('#toc .hide_toc').toggle(function() {
176
- $('#toc .top').slideUp('fast');
177
- $('#toc').toggleClass('hidden');
178
- $('#toc .title small').toggle();
179
- }, function() {
180
- $('#toc .top').slideDown('fast');
181
- $('#toc').toggleClass('hidden');
182
- $('#toc .title small').toggle();
183
- });
184
- $('#toc .float_toc').toggle(function() {
185
- $(this).text('float');
186
- $('#toc').toggleClass('nofloat');
187
- }, function() {
188
- $(this).text('left')
189
- $('#toc').toggleClass('nofloat');
190
- });
191
- }
192
-
193
- $(framesInit);
194
- $(createSourceLinks);
195
- $(createDefineLinks);
196
- $(createFullTreeLinks);
197
- $(fixBoxInfoHeights);
198
- $(searchFrameLinks);
199
- $(linkSummaries);
200
- $(keyboardShortcuts);
201
- $(summaryToggle);
202
- $(fixOutsideWorldLinks);
203
- $(generateTOC);
data/doc/js/full_list.js DELETED
@@ -1,149 +0,0 @@
1
- var inSearch = null;
2
- var searchIndex = 0;
3
- var searchCache = [];
4
- var searchString = '';
5
-
6
- function fullListSearch() {
7
- // generate cache
8
- searchCache = [];
9
- $('#full_list li').each(function() {
10
- var link = $(this).find('.object_link a');
11
- searchCache.push({name:link.text(), node:$(this), link:link});
12
- });
13
-
14
- $('#search input').keyup(function() {
15
- searchString = this.value.toLowerCase();
16
- if (searchString == "") {
17
- clearTimeout(inSearch);
18
- inSearch = null;
19
- $('#full_list, #content').removeClass('insearch');
20
- $('#full_list li').removeClass('found').each(function() {
21
-
22
- var link = $(this).find('.object_link a');
23
- link.text(link.text());
24
- });
25
- if (clicked) {
26
- clicked.parents('ul').each(function() {
27
- $(this).removeClass('collapsed').prev().removeClass('collapsed');
28
- });
29
- }
30
- highlight();
31
- }
32
- else {
33
- if (inSearch) clearTimeout(inSearch);
34
- searchIndex = 0;
35
- lastRowClass = '';
36
- $('#full_list, #content').addClass('insearch');
37
- $('#noresults').text('');
38
- searchItem();
39
- }
40
- });
41
-
42
- $('#search input').focus();
43
- $('#full_list').after("<div id='noresults'></div>")
44
- }
45
-
46
- var lastRowClass = '';
47
- function searchItem() {
48
- for (var i = 0; i < searchCache.length / 50; i++) {
49
- var item = searchCache[searchIndex];
50
- if (item.name.toLowerCase().indexOf(searchString) == -1) {
51
- item.node.removeClass('found');
52
- }
53
- else {
54
- item.node.css('padding-left', '10px').addClass('found');
55
- item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1');
56
- lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2';
57
- item.link.html(item.name.replace(new RegExp("(" +
58
- searchString.replace(/([\/.*+?|()\[\]{}\\])/g, "\\$1") + ")", "ig"),
59
- '<strong>$1</strong>'));
60
- }
61
-
62
- if (searchCache.length == searchIndex + 1) {
63
- return searchDone();
64
- }
65
- else {
66
- searchIndex++;
67
- }
68
- }
69
- inSearch = setTimeout('searchItem()', 0);
70
- }
71
-
72
- function searchDone() {
73
- highlight(true);
74
- if ($('#full_list li:visible').size() == 0) {
75
- $('#noresults').text('No results were found.').hide().fadeIn();
76
- }
77
- else {
78
- $('#noresults').text('');
79
- }
80
- $('#content').removeClass('insearch');
81
- clearTimeout(inSearch);
82
- inSearch = null;
83
- }
84
-
85
- clicked = null;
86
- function linkList() {
87
- $('#full_list li, #full_list li a:last').click(function(evt) {
88
- if ($(this).hasClass('toggle')) return true;
89
- if (this.tagName.toLowerCase() == "li") {
90
- var toggle = $(this).children('a.toggle');
91
- if (toggle.size() > 0 && evt.pageX < toggle.offset().left) {
92
- toggle.click();
93
- return false;
94
- }
95
- }
96
- if (clicked) clicked.removeClass('clicked');
97
- var win = window.top.frames.main ? window.top.frames.main : window.parent;
98
- if (this.tagName.toLowerCase() == "a") {
99
- clicked = $(this).parent('li').addClass('clicked');
100
- win.location = this.href;
101
- }
102
- else {
103
- clicked = $(this).addClass('clicked');
104
- win.location = $(this).find('a:last').attr('href');
105
- }
106
- return false;
107
- });
108
- }
109
-
110
- function collapse() {
111
- if (!$('#full_list').hasClass('class')) return;
112
- $('#full_list.class a.toggle').click(function() {
113
- $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed');
114
- highlight();
115
- return false;
116
- });
117
- $('#full_list.class ul').each(function() {
118
- $(this).addClass('collapsed').prev().addClass('collapsed');
119
- });
120
- $('#full_list.class').children().removeClass('collapsed');
121
- highlight();
122
- }
123
-
124
- function highlight(no_padding) {
125
- var n = 1;
126
- $('#full_list li:visible').each(function() {
127
- var next = n == 1 ? 2 : 1;
128
- $(this).removeClass("r" + next).addClass("r" + n);
129
- if (!no_padding && $('#full_list').hasClass('class')) {
130
- $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px');
131
- }
132
- n = next;
133
- });
134
- }
135
-
136
- function escapeShortcut() {
137
- $(document).keydown(function(evt) {
138
- if (evt.which == 27) {
139
- $('#search_frame', window.top.document).slideUp(100);
140
- $('#search a', window.top.document).removeClass('active inactive')
141
- $(window.top).focus();
142
- }
143
- });
144
- }
145
-
146
- $(escapeShortcut);
147
- $(fullListSearch);
148
- $(linkList);
149
- $(collapse);