rotp 4.0.0 → 6.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +19 -0
- data/.devcontainer/devcontainer.json +41 -0
- data/.github/workflows/release.yaml +36 -0
- data/.github/workflows/test.yaml +26 -0
- data/.release-please-manifest.json +3 -0
- data/CHANGELOG.md +91 -24
- data/Dockerfile-2.3 +1 -7
- data/Dockerfile-2.7 +11 -0
- data/Dockerfile-3.0 +12 -0
- data/Guardfile +1 -1
- data/README.md +64 -15
- data/bin/rotp +1 -1
- data/docker-compose.yml +37 -0
- data/lib/rotp/arguments.rb +6 -5
- data/lib/rotp/base32.rb +56 -30
- data/lib/rotp/cli.rb +4 -5
- data/lib/rotp/hotp.rb +6 -13
- data/lib/rotp/otp/uri.rb +78 -0
- data/lib/rotp/otp.rb +26 -25
- data/lib/rotp/totp.rb +13 -33
- data/lib/rotp/version.rb +1 -1
- data/lib/rotp.rb +2 -4
- data/release-please-config.json +12 -0
- data/rotp.gemspec +13 -15
- data/spec/lib/rotp/arguments_spec.rb +5 -6
- data/spec/lib/rotp/base32_spec.rb +45 -19
- data/spec/lib/rotp/cli_spec.rb +21 -6
- data/spec/lib/rotp/hotp_spec.rb +38 -17
- data/spec/lib/rotp/otp/uri_spec.rb +99 -0
- data/spec/lib/rotp/totp_spec.rb +61 -98
- data/spec/spec_helper.rb +1 -2
- metadata +25 -43
- data/.travis.yml +0 -8
- data/Dockerfile-1.9 +0 -15
- data/Dockerfile-2.1 +0 -16
- data/Rakefile +0 -9
- data/doc/ROTP/HOTP.html +0 -308
- data/doc/ROTP/OTP.html +0 -593
- data/doc/ROTP/TOTP.html +0 -493
- data/doc/Rotp.html +0 -179
- data/doc/_index.html +0 -144
- data/doc/class_list.html +0 -36
- data/doc/css/common.css +0 -1
- data/doc/css/full_list.css +0 -53
- data/doc/css/style.css +0 -310
- data/doc/file.README.html +0 -89
- data/doc/file_list.html +0 -38
- data/doc/frames.html +0 -13
- data/doc/index.html +0 -89
- data/doc/js/app.js +0 -203
- data/doc/js/full_list.js +0 -149
- data/doc/js/jquery.js +0 -154
- data/doc/method_list.html +0 -155
- data/doc/top-level-namespace.html +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d6cedb1952a6df3b069bb85d94e169d4aeb7878e6e4dde0dcb3fe4a2915a747
|
4
|
+
data.tar.gz: 2ad3bb2a4ef2575af9b976da0c59eb22b7e4d8b9e0a44e477329222feb567e09
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90ea9ec5403ad5e0953582e4a8c17369a0722c3f79d6b5a9d25e1f756a2cc024d01824a7e469a10dd98a7289aef6b34496dc6987565885fa01b3e8d0d6fb8e8c
|
7
|
+
data.tar.gz: aa7a667ef8de152cca8cd67df56d0f55a03ac7429f114d619bec1ac05178c015ba6c932f6fd651f27031c860927b81a3dc98bcd53ff7ef4080120a58404cd8f8
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.238.1/containers/ruby/.devcontainer/base.Dockerfile
|
2
|
+
|
3
|
+
# [Choice] Ruby version (use -bullseye variants on local arm64/Apple Silicon): 3, 3.1, 3.0, 2, 2.7, 3-bullseye, 3.1-bullseye, 3.0-bullseye, 2-bullseye, 2.7-bullseye, 3-buster, 3.1-buster, 3.0-buster, 2-buster, 2.7-buster
|
4
|
+
ARG VARIANT="3.1-bullseye"
|
5
|
+
FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT}
|
6
|
+
|
7
|
+
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
|
8
|
+
ARG NODE_VERSION="none"
|
9
|
+
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
10
|
+
|
11
|
+
# [Optional] Uncomment this section to install additional OS packages.
|
12
|
+
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
13
|
+
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
14
|
+
|
15
|
+
# [Optional] Uncomment this line to install additional gems.
|
16
|
+
# RUN gem install <your-gem-names-here>
|
17
|
+
|
18
|
+
# [Optional] Uncomment this line to install global node packages.
|
19
|
+
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
@@ -0,0 +1,41 @@
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
2
|
+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.1/containers/ruby
|
3
|
+
{
|
4
|
+
"name": "Ruby",
|
5
|
+
"build": {
|
6
|
+
"dockerfile": "Dockerfile",
|
7
|
+
"args": {
|
8
|
+
// Update 'VARIANT' to pick a Ruby version: 3, 3.1, 3.0, 2, 2.7
|
9
|
+
// Append -bullseye or -buster to pin to an OS version.
|
10
|
+
// Use -bullseye variants on local on arm64/Apple Silicon.
|
11
|
+
"VARIANT": "3-bullseye",
|
12
|
+
// Options
|
13
|
+
"NODE_VERSION": "16"
|
14
|
+
}
|
15
|
+
},
|
16
|
+
|
17
|
+
// Configure tool-specific properties.
|
18
|
+
"customizations": {
|
19
|
+
// Configure properties specific to VS Code.
|
20
|
+
"vscode": {
|
21
|
+
// Add the IDs of extensions you want installed when the container is created.
|
22
|
+
"extensions": [
|
23
|
+
"rebornix.Ruby"
|
24
|
+
]
|
25
|
+
}
|
26
|
+
},
|
27
|
+
|
28
|
+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
29
|
+
// "forwardPorts": [],
|
30
|
+
|
31
|
+
// Use 'postCreateCommand' to run commands after the container is created.
|
32
|
+
// "postCreateCommand": "ruby --version",
|
33
|
+
|
34
|
+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
35
|
+
"remoteUser": "vscode",
|
36
|
+
"features": {
|
37
|
+
"ghcr.io/devcontainers-contrib/features/act:1": {},
|
38
|
+
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
|
39
|
+
}
|
40
|
+
|
41
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
name: Release
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- 'main'
|
7
|
+
jobs:
|
8
|
+
release:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- uses: google-github-actions/release-please-action@v3
|
12
|
+
id: release
|
13
|
+
with:
|
14
|
+
release-type: ruby
|
15
|
+
package-name: rotp
|
16
|
+
version-file: "lib/rotp/version.rb"
|
17
|
+
# Checkout code if release was created
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
if: ${{ steps.release.outputs.release_created }}
|
20
|
+
# Setup ruby if a release was created
|
21
|
+
- uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: 3.2
|
24
|
+
bundler-cache: true
|
25
|
+
if: ${{ steps.release.outputs.release_created }}
|
26
|
+
- name: Run tests
|
27
|
+
run: bundle exec rspec
|
28
|
+
if: ${{ steps.release.outputs.release_created }}
|
29
|
+
# build gem and add to release
|
30
|
+
- name: Upload Release Artifact
|
31
|
+
if: ${{ steps.release.outputs.release_created }}
|
32
|
+
env:
|
33
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
34
|
+
run:
|
35
|
+
gem build *.gemspec
|
36
|
+
gh release upload ${{ steps.release.outputs.tag_name }} *.gem
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
pull_request:
|
7
|
+
types: [opened, reopened, synchronize]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
|
12
|
+
runs-on: ubuntu-latest
|
13
|
+
|
14
|
+
strategy:
|
15
|
+
matrix:
|
16
|
+
ruby-version: ['3.2', '3.0', '2.7', '2.3', truffleruby-head]
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v3
|
20
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
21
|
+
uses: ruby/setup-ruby@v1
|
22
|
+
with:
|
23
|
+
ruby-version: ${{ matrix.ruby-version }}
|
24
|
+
bundler-cache: true
|
25
|
+
- name: Run tests
|
26
|
+
run: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,100 +1,167 @@
|
|
1
|
-
|
1
|
+
# Changelog
|
2
2
|
|
3
|
-
|
3
|
+
## [6.3.0](https://github.com/mdp/rotp/compare/v6.2.2...v6.3.0) (2023-08-30)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* Allow for non-standard provisioning URI params, eg. image/icon ([#91](https://github.com/mdp/rotp/issues/91)) ([45d8aac](https://github.com/mdp/rotp/commit/45d8aac8356424897faf3a0dbda59f88b22df775))
|
9
|
+
|
10
|
+
## 6.2.2
|
11
|
+
|
12
|
+
- Removed `rjust` from `generate_otp` in favor of more time constant version
|
13
|
+
|
14
|
+
## 6.2.1
|
15
|
+
|
16
|
+
- Removed old rdoc folder that was triggering a security warning due to an
|
17
|
+
old version of JQuery being included in the HTML docs. This has no impact
|
18
|
+
on the Ruby library.
|
19
|
+
|
20
|
+
## 6.2.0
|
21
|
+
|
22
|
+
- Update to expand compatibility with Ruby 3. This was only a change to the
|
23
|
+
gemspec, no code changes were necessary.
|
24
|
+
|
25
|
+
## 6.1.0
|
26
|
+
|
27
|
+
- Fixing URI encoding issues again, breaking out into it's own module
|
28
|
+
due to the complexity - closes #100 (@atcruice)
|
29
|
+
- Add docker-compose.yml to help with easier testing
|
30
|
+
|
31
|
+
## 6.0.0
|
32
|
+
|
33
|
+
- Dropping support for Ruby <2.3 (Major version bump)
|
34
|
+
- Fix issue when using --enable-frozen-string-literal Ruby option #95 (jeremyevans)
|
35
|
+
- URI Encoding fix #94 (ksuh90)
|
36
|
+
- Update gems (rake, addressable)
|
37
|
+
- Update Travis tests to include Ruby 2.7
|
38
|
+
|
39
|
+
## 5.1.0
|
40
|
+
|
41
|
+
- Create `random_base32` to perform `random` to avoid breaking changes
|
42
|
+
- Still needed to bump to 5.x due to Base32 cleanup
|
43
|
+
|
44
|
+
## 5.0.0
|
45
|
+
|
46
|
+
- Clean up base32 implementation to match Google Autheticator
|
47
|
+
- BREAKING `Base32.random_base32` renamed to random
|
48
|
+
- The argument is now byte length vs output string length for more precise bit strengths
|
49
|
+
|
50
|
+
## 4.1.0
|
51
|
+
|
52
|
+
- Add a digest option to the CLI #83
|
53
|
+
- Fix provisioning URI is README #82
|
54
|
+
- Improvements to docs
|
55
|
+
|
56
|
+
## 4.0.2
|
57
|
+
|
58
|
+
- Fix gemspec requirment for Addressable
|
59
|
+
|
60
|
+
## 4.0.1
|
61
|
+
|
62
|
+
- Rubocop for style fixes
|
63
|
+
- Replace deprecated URI.encode with Addressable's version
|
64
|
+
|
65
|
+
## 4.0.0
|
4
66
|
|
5
67
|
- Simplify API
|
6
68
|
- Remove support for Ruby < 2.0
|
69
|
+
- BREAKING CHANGE: Removed optional second argument (`padding`) from:
|
70
|
+
- `HOTP#at`
|
71
|
+
- `OTP#generate_otp`
|
72
|
+
- `TOTP#at`
|
73
|
+
- `TOTP#now` (first argument)
|
7
74
|
|
8
|
-
|
75
|
+
## 3.3.1
|
9
76
|
|
10
77
|
- Add OpenSSL as a requirement for Ruby 2.5. Fixes #70 & #64
|
11
78
|
- Allow Base32 with padding. #71
|
12
79
|
- Prevent verify with drift being negative #69
|
13
80
|
|
14
|
-
|
81
|
+
## 3.3.0
|
15
82
|
|
16
83
|
- Add digest algorithm parameter for non SHA1 digests - #62 from @btalbot
|
17
84
|
|
18
|
-
|
85
|
+
## 3.2.0
|
19
86
|
|
20
87
|
- Add 'verify_with_drift_and_prior' to prevent prior token use - #58 from @jlfaber
|
21
88
|
|
22
|
-
|
89
|
+
## 3.1.0
|
23
90
|
|
24
91
|
- Add Add digits paramater to provisioning URI. #54 from @sbc100
|
25
92
|
|
26
|
-
|
93
|
+
## 3.0.1
|
27
94
|
|
28
95
|
- Use SecureRandom. See mdp/rotp/pull/52
|
29
96
|
|
30
|
-
|
97
|
+
## 3.0.0
|
31
98
|
|
32
99
|
- Provisioning URL includes issuer label per RFC 5234 See mdp/rotp/pull/51
|
33
100
|
|
34
|
-
|
101
|
+
## 2.1.2
|
35
102
|
|
36
103
|
- Remove string literals to prepare immutable strings in Ruby 3.0
|
37
104
|
|
38
|
-
|
105
|
+
## 2.1.1
|
39
106
|
|
40
107
|
- Reorder the params for Windows Phone Authenticator - #43
|
41
108
|
|
42
|
-
|
109
|
+
## 2.1.0
|
43
110
|
|
44
111
|
- Add a CLI for generating OTP's mdp/rotp/pull/35
|
45
112
|
|
46
|
-
|
113
|
+
## 2.0.0
|
47
114
|
|
48
115
|
- Move to only comparing string OTP's.
|
49
116
|
|
50
|
-
|
117
|
+
## 1.7.0
|
51
118
|
|
52
119
|
- Move to only comparing string OTP's. See mdp/rotp/issues/32 - Moved to 2.0.0 - yanked from RubyGems
|
53
120
|
|
54
|
-
|
121
|
+
## 1.6.1
|
55
122
|
|
56
123
|
- Remove deprecation warning in Ruby 2.1.0 (@ylansegal)
|
57
124
|
- Add Ruby 2.0 and 2.1 to Travis
|
58
125
|
|
59
|
-
|
126
|
+
## 1.6.0
|
60
127
|
|
61
128
|
- Add verify_with_retries to HOTP
|
62
129
|
- Fix 'cgi' require and global DEFAULT_INTERVAL
|
63
130
|
|
64
|
-
|
131
|
+
## 1.5.0
|
65
132
|
|
66
133
|
- Add support for "issuer" parameter on provisioning url
|
67
134
|
- Add support for "period/interval" parameter on provisioning url
|
68
135
|
|
69
|
-
|
136
|
+
## 1.4.6
|
70
137
|
|
71
138
|
- Revert to previous Base32
|
72
139
|
|
73
|
-
|
140
|
+
## 1.4.5
|
74
141
|
|
75
142
|
- Fix and test correct implementation of Base32
|
76
143
|
|
77
|
-
|
144
|
+
## 1.4.4
|
78
145
|
|
79
146
|
- Fix issue with base32 decoding of strings in a length that's not a multiple of 8
|
80
147
|
|
81
|
-
|
148
|
+
## 1.4.3
|
82
149
|
|
83
150
|
- Bugfix on padding
|
84
151
|
|
85
|
-
|
152
|
+
## 1.4.2
|
86
153
|
|
87
154
|
- Better padding options (Pad the output with leading 0's)
|
88
155
|
|
89
|
-
|
156
|
+
## 1.4.1
|
90
157
|
|
91
158
|
- Clean up drift logic
|
92
159
|
|
93
|
-
|
160
|
+
## 1.4.0
|
94
161
|
|
95
162
|
- Added clock drift support via 'verify_with_drift' for TOTP
|
96
163
|
|
97
|
-
|
164
|
+
## 1.3.0
|
98
165
|
|
99
166
|
- Added support for Ruby 1.9.x
|
100
167
|
- Removed dependency on Base32
|
data/Dockerfile-2.3
CHANGED
@@ -1,16 +1,10 @@
|
|
1
1
|
FROM ruby:2.3
|
2
2
|
|
3
|
-
# throw errors if Gemfile has been modified since Gemfile.lock
|
4
|
-
RUN bundle config --global frozen 1
|
5
|
-
|
6
3
|
RUN mkdir -p /usr/src/app
|
7
4
|
WORKDIR /usr/src/app
|
8
5
|
|
9
6
|
COPY Gemfile /usr/src/app/
|
10
|
-
COPY Gemfile.lock /usr/src/app/
|
11
7
|
COPY . /usr/src/app
|
12
8
|
RUN bundle install
|
13
9
|
|
14
|
-
|
15
|
-
CMD ["bundler", "exec", "rspec"]
|
16
|
-
|
10
|
+
CMD ["bundle", "exec", "rspec"]
|
data/Dockerfile-2.7
ADDED
data/Dockerfile-3.0
ADDED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,24 @@
|
|
1
|
+
## Webauthn and the future of 2FA
|
2
|
+
|
3
|
+
Although this library will continue to be maintained, if you're implementing a 2FA solution today, you should take a look at [Webauthn](https://webauthn.guide/). It doesn't involve shared secrets and it's supported by most modern browsers and operating systems.
|
4
|
+
|
5
|
+
### Ruby resources for Webauthn
|
6
|
+
|
7
|
+
- [Multi-Factor Authentication for Rails With WebAuthn and Devise](https://www.honeybadger.io/blog/multi-factor-2fa-authentication-rails-webauthn-devise/)
|
8
|
+
- [Webauthn Ruby Gem](https://github.com/cedarcode/webauthn-ruby)
|
9
|
+
- [Rails demo app with Webauthn](https://github.com/cedarcode/webauthn-rails-demo-app)
|
10
|
+
|
11
|
+
----
|
12
|
+
|
1
13
|
# The Ruby One Time Password Library
|
2
14
|
|
3
|
-
[![Build Status](https://
|
15
|
+
[![Build Status](https://github.com/mdp/rotp/actions/workflows/test.yaml/badge.svg)](https://github.com/mdp/rotp/actions/workflows/test.yaml)
|
4
16
|
[![Gem Version](https://badge.fury.io/rb/rotp.svg)](https://rubygems.org/gems/rotp)
|
17
|
+
[![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://www.rubydoc.info/github/mdp/rotp/master)
|
5
18
|
[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/mdp/rotp/blob/master/LICENSE)
|
6
19
|
|
7
|
-
|
20
|
+
|
21
|
+
A ruby library for generating and validating one time passwords (HOTP & TOTP) according to [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226) and [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238).
|
8
22
|
|
9
23
|
ROTP is compatible with [Google Authenticator](https://github.com/google/google-authenticator) available for [Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) and [iPhone](https://itunes.apple.com/en/app/google-authenticator/id388497605) and any other TOTP based implementations.
|
10
24
|
|
@@ -13,15 +27,28 @@ Many websites use this for [multi-factor authentication](https://www.youtube.com
|
|
13
27
|
## Dependencies
|
14
28
|
|
15
29
|
* OpenSSL
|
16
|
-
* Ruby 2.
|
30
|
+
* Ruby 2.3 or higher
|
17
31
|
|
18
|
-
## Breaking changes
|
32
|
+
## Breaking changes
|
33
|
+
|
34
|
+
### Breaking changes in >= 6.0
|
35
|
+
|
36
|
+
- Dropping support for Ruby <2.3
|
37
|
+
|
38
|
+
### Breaking changes in >= 5.0
|
39
|
+
|
40
|
+
- `ROTP::Base32.random_base32` is now `ROTP::Base32.random` and the argument
|
41
|
+
has changed from secret string length to byte length to allow for more
|
42
|
+
precision. There is an alias to allow for `random_base32` for the time being.
|
43
|
+
- Cleaned up the Base32 implementation to match Google Authenticator's version.
|
44
|
+
|
45
|
+
### Breaking changes in >= 4.0
|
19
46
|
|
20
47
|
- Simplified API
|
21
|
-
- `verify` now takes options for `drift` and `after`
|
48
|
+
- `verify` now takes options for `drift` and `after`,`padding` is no longer an option
|
22
49
|
- `verify` returns a timestamp if true, nil if false
|
23
50
|
- Dropping support for Ruby < 2.0
|
24
|
-
- Docs for 3.x can be found [here](https://github.com/mdp/rotp/tree/v3.
|
51
|
+
- Docs for 3.x can be found [here](https://github.com/mdp/rotp/tree/v3.x)
|
25
52
|
|
26
53
|
## Installation
|
27
54
|
|
@@ -56,8 +83,8 @@ hotp.at(1) # => "595254"
|
|
56
83
|
hotp.at(1401) # => "259769"
|
57
84
|
|
58
85
|
# OTP verified with a counter
|
59
|
-
hotp.verify("
|
60
|
-
hotp.verify("
|
86
|
+
hotp.verify("259769", 1401) # => 1401
|
87
|
+
hotp.verify("259769", 1402) # => nil
|
61
88
|
```
|
62
89
|
|
63
90
|
### Preventing reuse of Time based OTP's
|
@@ -68,18 +95,21 @@ the interval window (default 30 seconds)
|
|
68
95
|
The following is an example of this in action:
|
69
96
|
|
70
97
|
```ruby
|
71
|
-
User.find(someUserID)
|
98
|
+
user = User.find(someUserID)
|
72
99
|
totp = ROTP::TOTP.new(user.otp_secret)
|
73
100
|
totp.now # => "492039"
|
74
101
|
|
102
|
+
# Let's take a look at the last time the user authenticated with an OTP
|
75
103
|
user.last_otp_at # => 1432703530
|
76
104
|
|
77
105
|
# Verify the OTP
|
78
106
|
last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> 1472145760
|
79
107
|
# ROTP returns the timestamp(int) of the current period
|
108
|
+
|
80
109
|
# Store this on the user's account
|
81
110
|
user.update(last_otp_at: last_otp_at)
|
82
|
-
|
111
|
+
|
112
|
+
# Someone attempts to reuse the OTP inside the 30s window
|
83
113
|
last_otp_at = totp.verify("492039", after: user.last_otp_at) #=> nil
|
84
114
|
# It fails to verify because we are still in the same 30s interval window
|
85
115
|
```
|
@@ -104,7 +134,7 @@ totp.verify("250939", drift_behind: 15, at: now + 45) # => nil
|
|
104
134
|
### Generating a Base32 Secret key
|
105
135
|
|
106
136
|
```ruby
|
107
|
-
ROTP::Base32.
|
137
|
+
ROTP::Base32.random # returns a 160 bit (32 character) base32 secret. Compatible with Google Authenticator
|
108
138
|
```
|
109
139
|
|
110
140
|
Note: The Base32 format conforms to [RFC 4648 Base32](http://en.wikipedia.org/wiki/Base32#RFC_4648_Base32_alphabet)
|
@@ -115,8 +145,11 @@ Provisioning URI's generated by ROTP are compatible with most One Time Password
|
|
115
145
|
Google Authenticator.
|
116
146
|
|
117
147
|
```ruby
|
118
|
-
totp.
|
119
|
-
|
148
|
+
totp = ROTP::TOTP.new("base32secret3232", issuer: "My Service")
|
149
|
+
totp.provisioning_uri("alice@google.com") # => 'otpauth://totp/My%20Service:alice%40google.com?secret=base32secret3232&issuer=My%20Service'
|
150
|
+
|
151
|
+
hotp = ROTP::HOTP.new("base32secret3232", issuer: "My Service")
|
152
|
+
hotp.provisioning_uri("alice@google.com", 0) # => 'otpauth://hotp/My%20Service:alice%40google.com?secret=base32secret3232&issuer=My%20Service&counter=0'
|
120
153
|
```
|
121
154
|
|
122
155
|
This can then be rendered as a QR Code which the user can scan using their mobile phone and the appropriate application.
|
@@ -143,9 +176,25 @@ bundle install
|
|
143
176
|
bundle exec rspec
|
144
177
|
```
|
145
178
|
|
179
|
+
### Testing with Docker
|
180
|
+
|
181
|
+
In order to make it easier to test against different ruby version, ROTP comes
|
182
|
+
with a set of Dockerfiles for each version that we test against in Travis
|
183
|
+
|
184
|
+
```bash
|
185
|
+
docker build -f Dockerfile-2.6 -t rotp_2.6 .
|
186
|
+
docker run --rm -v $(pwd):/usr/src/app rotp_2.6
|
187
|
+
```
|
188
|
+
|
189
|
+
Alternately, you may use docker-compose to run all the tests:
|
190
|
+
|
191
|
+
```
|
192
|
+
docker-compose up
|
193
|
+
```
|
194
|
+
|
146
195
|
## Executable Usage
|
147
196
|
|
148
|
-
The rotp rubygem includes
|
197
|
+
The rotp rubygem includes CLI version to help with testing and debugging
|
149
198
|
|
150
199
|
```bash
|
151
200
|
# Try this to get an overview of the commands
|
@@ -162,7 +211,7 @@ Have a look at the [contributors graph](https://github.com/mdp/rotp/graphs/contr
|
|
162
211
|
|
163
212
|
## License
|
164
213
|
|
165
|
-
MIT Copyright (C)
|
214
|
+
MIT Copyright (C) 2019 by Mark Percival, see [LICENSE](https://github.com/mdp/rotp/blob/master/LICENSE) for details.
|
166
215
|
|
167
216
|
## Other implementations
|
168
217
|
|
data/bin/rotp
CHANGED
data/docker-compose.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
version: "3.8"
|
2
|
+
services:
|
3
|
+
ruby_2_3:
|
4
|
+
build:
|
5
|
+
context: .
|
6
|
+
dockerfile: Dockerfile-2.3
|
7
|
+
volumes:
|
8
|
+
- "./lib:/usr/src/app/lib"
|
9
|
+
- "./spec:/usr/src/app/spec"
|
10
|
+
ruby_2_5:
|
11
|
+
build:
|
12
|
+
context: .
|
13
|
+
dockerfile: Dockerfile-2.5
|
14
|
+
volumes:
|
15
|
+
- "./lib:/usr/src/app/lib"
|
16
|
+
- "./spec:/usr/src/app/spec"
|
17
|
+
ruby_2_6:
|
18
|
+
build:
|
19
|
+
context: .
|
20
|
+
dockerfile: Dockerfile-2.6
|
21
|
+
volumes:
|
22
|
+
- "./lib:/usr/src/app/lib"
|
23
|
+
- "./spec:/usr/src/app/spec"
|
24
|
+
ruby_2_7:
|
25
|
+
build:
|
26
|
+
context: .
|
27
|
+
dockerfile: Dockerfile-2.7
|
28
|
+
volumes:
|
29
|
+
- "./lib:/usr/src/app/lib"
|
30
|
+
- "./spec:/usr/src/app/spec"
|
31
|
+
ruby_3_0:
|
32
|
+
build:
|
33
|
+
context: .
|
34
|
+
dockerfile: Dockerfile-3.0
|
35
|
+
volumes:
|
36
|
+
- "./lib:/usr/src/app/lib"
|
37
|
+
- "./spec:/usr/src/app/spec"
|
data/lib/rotp/arguments.rb
CHANGED
@@ -3,7 +3,6 @@ require 'ostruct'
|
|
3
3
|
|
4
4
|
module ROTP
|
5
5
|
class Arguments
|
6
|
-
|
7
6
|
def initialize(filename, arguments)
|
8
7
|
@filename = filename
|
9
8
|
@arguments = Array(arguments)
|
@@ -32,11 +31,11 @@ module ROTP
|
|
32
31
|
|
33
32
|
def parse
|
34
33
|
return options!.mode = :help if arguments.empty?
|
35
|
-
parser.parse arguments
|
36
34
|
|
35
|
+
parser.parse arguments
|
37
36
|
rescue OptionParser::InvalidOption => exception
|
38
37
|
options!.mode = :help
|
39
|
-
options!.warnings = red(exception.message +
|
38
|
+
options!.warnings = red(exception.message + '. Try --help for help.')
|
40
39
|
end
|
41
40
|
|
42
41
|
def parser
|
@@ -69,6 +68,10 @@ module ROTP
|
|
69
68
|
parser.on_tail('-h', '--help', 'Show this message') do
|
70
69
|
options!.mode = :help
|
71
70
|
end
|
71
|
+
|
72
|
+
parser.on('-d', '--digest [ALGORITHM]', 'Use algorithm for the digest (default sha1)') do |digest|
|
73
|
+
options!.digest = digest
|
74
|
+
end
|
72
75
|
end
|
73
76
|
end
|
74
77
|
|
@@ -83,7 +86,5 @@ module ROTP
|
|
83
86
|
def red(string)
|
84
87
|
"\033[31m#{string}\033[0m"
|
85
88
|
end
|
86
|
-
|
87
89
|
end
|
88
90
|
end
|
89
|
-
|