rotp 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,13 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'timecop'
4
- require 'rspec'
5
- require 'rspec/autorun'
6
-
7
1
  require 'rotp'
2
+ require 'timecop'
8
3
 
9
4
  RSpec.configure do |config|
10
- # some (optional) config here
5
+ config.disable_monkey_patching!
6
+ config.raise_errors_for_deprecations!
7
+ config.color = true
8
+ config.fail_fast = true
9
+
10
+ config.before do
11
+ Timecop.return
12
+ end
11
13
  end
metadata CHANGED
@@ -1,71 +1,89 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rotp
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Percival
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-22 00:00:00.000000000 Z
11
+ date: 2015-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: guard-rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.5.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.5.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - ~>
31
+ - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: 10.1.0
33
+ version: 10.4.2
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - ~>
38
+ - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: 10.1.0
40
+ version: 10.4.2
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rspec
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
- - - ~>
45
+ - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: 2.13.0
47
+ version: 3.1.0
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
- - - ~>
52
+ - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: 2.13.0
54
+ version: 3.1.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: timecop
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - '>='
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '0'
61
+ version: 0.7.1
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - '>='
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0'
68
+ version: 0.7.1
55
69
  description: Works for both HOTP and TOTP, and includes QR Code provisioning
56
70
  email:
57
71
  - mark@markpercival.us
58
- executables: []
72
+ executables:
73
+ - rotp
59
74
  extensions: []
60
75
  extra_rdoc_files: []
61
76
  files:
62
- - .gitignore
63
- - .rspec
64
- - .travis.yml
77
+ - ".gitignore"
78
+ - ".travis.yml"
79
+ - CHANGELOG.md
65
80
  - Gemfile
81
+ - Gemfile.lock
82
+ - Guardfile
66
83
  - LICENSE
67
- - README.markdown
84
+ - README.md
68
85
  - Rakefile
86
+ - bin/rotp
69
87
  - doc/ROTP/HOTP.html
70
88
  - doc/ROTP/OTP.html
71
89
  - doc/ROTP/TOTP.html
@@ -85,16 +103,20 @@ files:
85
103
  - doc/method_list.html
86
104
  - doc/top-level-namespace.html
87
105
  - lib/rotp.rb
106
+ - lib/rotp/arguments.rb
88
107
  - lib/rotp/base32.rb
108
+ - lib/rotp/cli.rb
89
109
  - lib/rotp/hotp.rb
90
110
  - lib/rotp/otp.rb
91
111
  - lib/rotp/totp.rb
92
112
  - lib/rotp/version.rb
93
113
  - rotp.gemspec
94
- - spec/base_spec.rb
95
- - spec/hotp_spec.rb
114
+ - spec/lib/rotp/arguments_spec.rb
115
+ - spec/lib/rotp/base32_spec.rb
116
+ - spec/lib/rotp/cli_spec.rb
117
+ - spec/lib/rotp/hotp_spec.rb
118
+ - spec/lib/rotp/totp_spec.rb
96
119
  - spec/spec_helper.rb
97
- - spec/totp_spec.rb
98
120
  homepage: http://github.com/mdp/rotp
99
121
  licenses:
100
122
  - MIT
@@ -105,18 +127,24 @@ require_paths:
105
127
  - lib
106
128
  required_ruby_version: !ruby/object:Gem::Requirement
107
129
  requirements:
108
- - - '>='
130
+ - - ">="
109
131
  - !ruby/object:Gem::Version
110
132
  version: '0'
111
133
  required_rubygems_version: !ruby/object:Gem::Requirement
112
134
  requirements:
113
- - - '>='
135
+ - - ">="
114
136
  - !ruby/object:Gem::Version
115
137
  version: '0'
116
138
  requirements: []
117
139
  rubyforge_project: rotp
118
- rubygems_version: 2.0.2
140
+ rubygems_version: 2.4.5
119
141
  signing_key:
120
142
  specification_version: 4
121
143
  summary: A Ruby library for generating and verifying one time passwords
122
- test_files: []
144
+ test_files:
145
+ - spec/lib/rotp/arguments_spec.rb
146
+ - spec/lib/rotp/base32_spec.rb
147
+ - spec/lib/rotp/cli_spec.rb
148
+ - spec/lib/rotp/hotp_spec.rb
149
+ - spec/lib/rotp/totp_spec.rb
150
+ - spec/spec_helper.rb
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- # /.rspec
2
- --format nested
3
- --color
data/README.markdown DELETED
@@ -1,163 +0,0 @@
1
- # ROTP - The Ruby One Time Password Library
2
- [![Build Status](https://secure.travis-ci.org/mdp/rotp.png)](http://travis-ci.org/mdp/rotp)
3
-
4
- A ruby library for generating one time passwords (HOTP & TOTP) according to [ RFC 4226 ](http://tools.ietf.org/html/rfc4226) and [ RFC 6238 ](http://tools.ietf.org/html/rfc6238)
5
-
6
- This is compatible with Google Authenticator apps available for Android and iPhone, and now in use on GMail
7
-
8
- ## Quick overview of using One Time Passwords on your phone
9
-
10
- * OTP's involve a shared secret, stored both on the phone and the server
11
- * OTP's can be generated on a phone without internet connectivity (AT&T mode)
12
- * OTP's should always be used as a second factor of authentication (if your phone is lost, your account is still secured with a password)
13
- * Google Authenticator allows you to store multiple OTP secrets and provision those using a QR Code (no more typing in the secret)
14
-
15
- ## Dependencies
16
-
17
- * OpenSSL
18
-
19
- ## Installation
20
-
21
- gem install rotp
22
-
23
- ## Use
24
-
25
- ### Time based OTP's
26
-
27
- totp = ROTP::TOTP.new("base32secret3232")
28
- totp.now # => "492039"
29
-
30
- # OTP verified for current time
31
- totp.verify("492039") # => true
32
- sleep 30
33
- totp.verify("492039") # => false
34
-
35
- ### Counter based OTP's
36
-
37
- hotp = ROTP::HOTP.new("base32secretkey3232")
38
- hotp.at(0) # => "260182"
39
- hotp.at(1) # => "055283"
40
- hotp.at(1401) # => "316439"
41
-
42
- # OTP verified with a counter
43
- totp.verify("316439", 1401) # => true
44
- totp.verify("316439", 1402) # => false
45
-
46
- ### Generating a Base32 Secret key
47
-
48
- ROTP::Base32.random_base32 # returns a 16 character base32 secret. Compatible with Google Authenticator
49
-
50
- ### Google Authenticator Compatible
51
-
52
- The library works with the Google Authenticator iPhone and Android app, and also
53
- includes the ability to generate provisioning URI's for use with the QR Code scanner
54
- built into the app.
55
-
56
- totp.provisioning_uri("alice@google.com") # => 'otpauth://totp/alice@google.com?secret=JBSWY3DPEHPK3PXP'
57
- hotp.provisioning_uri("alice@google.com", 0) # => 'otpauth://hotp/alice@google.com?secret=JBSWY3DPEHPK3PXP&counter=0'
58
-
59
- This can then be rendered as a QR Code which can then be scanned and added to the users
60
- list of OTP credentials.
61
-
62
- #### Working example
63
-
64
- Scan the following barcode with your phone, using Google Authenticator
65
-
66
- ![QR Code for OTP](http://chart.apis.google.com/chart?cht=qr&chs=250x250&chl=otpauth%3A%2F%2Ftotp%2Falice%40google.com%3Fsecret%3DJBSWY3DPEHPK3PXP)
67
-
68
- Now run the following and compare the output
69
-
70
- require 'rubygems'
71
- require 'rotp'
72
- totp = ROTP::TOTP.new("JBSWY3DPEHPK3PXP")
73
- p "Current OTP: #{totp.now}"
74
-
75
- ### Testing
76
-
77
- bundle install
78
- bundle exec rspec spec/*
79
-
80
- ### Contributors
81
-
82
- git shortlog -s -n
83
-
84
- 47 Mark Percival
85
- 6 David Vrensk
86
- 1 Guillaume Rose
87
- 1 Micah Gates
88
- 1 Michael Brodhead & Shai Rosenfeld
89
- 1 Nathan Reynolds
90
- 1 Shai Rosenfeld
91
- 1 Shai Rosenfeld & Michael Brodhead
92
-
93
- ### Changelog
94
-
95
-
96
- #### 2.0.0
97
-
98
- - Move to only comparing string OTP's.
99
-
100
- #### 1.7.1
101
-
102
- - Revert to former API
103
-
104
- #### 1.7.0
105
-
106
- - Move to only comparing string OTP's. See mdp/rotp/issues/32 - Moved to 2.0.0
107
-
108
- #### 1.6.1
109
-
110
- - Remove deprecation warning in Ruby 2.1.0 (@ylansegal)
111
- - Add Ruby 2.0 and 2.1 to Travis
112
-
113
- #### 1.6.0
114
-
115
- - Add verify_with_retries to HOTP
116
- - Fix 'cgi' require and global DEFAULT_INTERVAL
117
-
118
- #### 1.5.0
119
-
120
- - Add support for "issuer" parameter on provisioning url
121
- - Add support for "period/interval" parameter on provisioning url
122
-
123
- #### 1.4.6
124
-
125
- - Revert to previous Base32
126
-
127
- #### 1.4.5
128
-
129
- - Fix and test correct implementation of Base32
130
-
131
- #### 1.4.4
132
-
133
- - Fix issue with base32 decoding of strings in a length that's not a multiple of 8
134
-
135
- #### 1.4.3
136
-
137
- - Bugfix on padding
138
-
139
- #### 1.4.2
140
-
141
- - Better padding options (Pad the output with leading 0's)
142
-
143
- #### 1.4.1
144
-
145
- - Clean up drift logic
146
-
147
- #### 1.4.0
148
-
149
- - Added clock drift support via 'verify_with_drift' for TOTP
150
-
151
- ####1.3.0
152
-
153
- - Added support for Ruby 1.9.x
154
- - Removed dependency on Base32
155
-
156
- ### License
157
-
158
- MIT Licensed
159
-
160
- ### See also:
161
-
162
- Python port PYOTP by [Nathan Reynolds](https://github.com/nathforge) - [https://github.com/nathforge/pyotp](https://github.com/nathforge/pyotp)
163
- PHP port OTPHP by [Le Lag](https://github.com/lelag) - [https://github.com/lelag/otphp](https://github.com/lelag/otphp)
data/spec/base_spec.rb DELETED
@@ -1,27 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
-
3
- describe "the Base32 implementation" do
4
- it "should be 16 characters by default" do
5
- ROTP::Base32.random_base32.length.should == 16
6
- ROTP::Base32.random_base32.should match /\A[a-z2-7]+\z/
7
- end
8
- it "should be allow a specific length" do
9
- ROTP::Base32.random_base32(32).length.should == 32
10
- end
11
- it "raise a sane error on a bad decode" do
12
- expect { ROTP::Base32.decode("4BCDEFG234BCDEF1") }.to \
13
- raise_error(ROTP::Base32::Base32Error, "Invalid Base32 Character - '1'")
14
- end
15
- it "should correctly decode a string" do
16
- ROTP::Base32.decode("F").unpack('H*').first.should == "28"
17
- ROTP::Base32.decode("23").unpack('H*').first.should == "d6"
18
- ROTP::Base32.decode("234").unpack('H*').first.should == "d6f8"
19
- ROTP::Base32.decode("234A").unpack('H*').first.should == "d6f800"
20
- ROTP::Base32.decode("234B").unpack('H*').first.should == "d6f810"
21
- ROTP::Base32.decode("234BCD").unpack('H*').first.should == "d6f8110c"
22
- ROTP::Base32.decode("234BCDE").unpack('H*').first.should == "d6f8110c80"
23
- ROTP::Base32.decode("234BCDEFG").unpack('H*').first.should == "d6f8110c8530"
24
- ROTP::Base32.decode("234BCDEFG234BCDEFG").unpack('H*').first.should == "d6f8110c8536b7c0886429"
25
- end
26
- end
27
-
data/spec/hotp_spec.rb DELETED
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ROTP::HOTP do
4
- before(:all) { @counter = 1234 }
5
-
6
- subject { ROTP::HOTP.new('a' * 32) }
7
-
8
- it "should generate a string OTP given a count" do
9
- subject.at(@counter).should == "161024"
10
- end
11
- it "should generate a number if padding is set to false" do
12
- subject.at(@counter, false).should == 161024
13
- end
14
- it "should not verify a number" do
15
- expect {
16
- subject.verify(161024, @counter)
17
- }.to raise_error
18
- end
19
- it "should verify a string" do
20
- subject.verify("161024", @counter).should be_true
21
- end
22
- it "should output its provisioning URI" do
23
- url = subject.provisioning_uri('mark@percival')
24
- params = CGI::parse(URI::parse(url).query)
25
- url.should match(/otpauth:\/\/hotp.+/)
26
- params["secret"].first.should == "a" * 32
27
- end
28
-
29
- context "with retries" do
30
- it "should verify that retry is a valid number" do
31
- subject.verify_with_retries("161024", @counter, -1).should be_false
32
- subject.verify_with_retries("161024", @counter, 0).should be_false
33
- end
34
-
35
- it "should verify up to the total number of retries and return the counter" do
36
- subject.verify_with_retries("161024", @counter - 10, 10).should == @counter
37
- end
38
-
39
- it "should verify that retry is a valid number" do
40
- subject.verify_with_retries("161024", @counter - 20, 10).should be_false
41
- end
42
- end
43
- end
44
-
45
- describe "HOTP example values from the rfc" do
46
- it "should match the RFC" do
47
- # 12345678901234567890 in Base32
48
- # GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
49
- hotp = ROTP::HOTP.new("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
50
- hotp.at(0).should ==("755224")
51
- hotp.at(1).should ==("287082")
52
- hotp.at(2).should ==("359152")
53
- hotp.at(3).should ==("969429")
54
- hotp.at(4).should ==("338314")
55
- hotp.at(5).should ==("254676")
56
- hotp.at(6).should ==("287922")
57
- hotp.at(7).should ==("162583")
58
- hotp.at(8).should ==("399871")
59
- hotp.at(9).should ==("520489")
60
- end
61
- it "should verify an OTP and not allow reuse" do
62
- hotp = ROTP::HOTP.new("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
63
- hotp.verify("520489", 9).should be_true
64
- hotp.verify("520489", 10).should be_false
65
- end
66
- end
data/spec/totp_spec.rb DELETED
@@ -1,115 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe ROTP::TOTP do
4
- before(:all) { @now = Time.utc(2012,1,1) }
5
-
6
- subject { ROTP::TOTP.new("JBSWY3DPEHPK3PXP") }
7
-
8
- it "should generate a number given a number" do
9
- subject.at(@now, false).should == 68212
10
- end
11
-
12
- it "should generate a number as a padded string by default" do
13
- subject.at(@now).should == "068212"
14
- end
15
-
16
- # Users of the lib
17
- it "should not verify a number" do
18
- expect {
19
- subject.verify(68212, @now)
20
- }.to raise_error
21
- end
22
- it "should not verify an unpadded string" do
23
- subject.verify("68212", @now).should be_false
24
- end
25
- it "should verify a string" do
26
- subject.verify("068212", @now).should be_true
27
- end
28
-
29
- it "should output its provisioning URI" do
30
- url = subject.provisioning_uri('mark@percival')
31
- params = CGI::parse(URI::parse(url).query)
32
- url.should match(/otpauth:\/\/totp.+/)
33
- params["secret"].first.should == "JBSWY3DPEHPK3PXP"
34
- end
35
-
36
- context "with issuer" do
37
- subject { ROTP::TOTP.new("JBSWY3DPEHPK3PXP", :issuer => "FooCo") }
38
- it "should output its provisioning URI with issuer" do
39
- url = subject.provisioning_uri('mark@percival')
40
- params = CGI::parse(URI::parse(url).query)
41
- url.should match(/otpauth:\/\/totp.+/)
42
- params["secret"].first.should == "JBSWY3DPEHPK3PXP"
43
- params["issuer"].first.should == "FooCo"
44
- end
45
- end
46
-
47
- context "with non default interval" do
48
- subject { ROTP::TOTP.new("JBSWY3DPEHPK3PXP", :interval => 60) }
49
- it "should output its provisioning URI with issuer" do
50
- url = subject.provisioning_uri('mark@percival')
51
- params = CGI::parse(URI::parse(url).query)
52
- url.should match(/otpauth:\/\/totp.+/)
53
- params["secret"].first.should == "JBSWY3DPEHPK3PXP"
54
- params["period"].first.should == "60"
55
- end
56
- end
57
-
58
-
59
- context "with drift" do
60
- it "should verify a number" do
61
- subject.verify_with_drift("068212", 0, @now).should be_true
62
- end
63
- it "should verify a string" do
64
- subject.verify_with_drift("068212", 0, @now).should be_true
65
- end
66
- it "should verify a slightly old number" do
67
- subject.verify_with_drift(subject.at(@now - 30), 60, @now).should be_true
68
- end
69
- it "should verify a slightly new number" do
70
- subject.verify_with_drift(subject.at(@now + 60), 60, @now).should be_true
71
- end
72
- it "should reject a number that is outside the allowed drift" do
73
- subject.verify_with_drift(subject.at(@now - 60), 30, @now).should be_false
74
- end
75
- context "with drift that is not a multiple of the TOTP interval" do
76
- it "should verify a slightly old number" do
77
- subject.verify_with_drift(subject.at(@now - 45), 45, @now).should be_true
78
- end
79
- it "should verify a slightly new number" do
80
- subject.verify_with_drift(subject.at(@now + 40), 40, @now).should be_true
81
- end
82
- end
83
- end
84
- end
85
-
86
- describe "TOTP example values from the documented output" do
87
- it "should match the RFC" do
88
- totp = ROTP::TOTP.new("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")
89
- totp.at(1111111111).should ==("050471")
90
- totp.at(1234567890).should ==("005924")
91
- totp.at(2000000000).should ==("279037")
92
- end
93
-
94
- it "should match the Google Authenticator output" do
95
- totp = ROTP::TOTP.new("wrn3pqx5uqxqvnqr")
96
- Timecop.freeze(Time.at(1297553958)) do
97
- totp.now.should ==("102705")
98
- end
99
- end
100
- it "should match Dropbox 26 char secret output" do
101
- totp = ROTP::TOTP.new("tjtpqea6a42l56g5eym73go2oa")
102
- Timecop.freeze(Time.at(1378762454)) do
103
- totp.now.should ==("747864")
104
- end
105
- end
106
- it "should validate a time based OTP" do
107
- totp = ROTP::TOTP.new("wrn3pqx5uqxqvnqr")
108
- Timecop.freeze(Time.at(1297553958)) do
109
- totp.verify("102705").should be_true
110
- end
111
- Timecop.freeze(Time.at(1297553958 + 30)) do
112
- totp.verify("102705").should be_false
113
- end
114
- end
115
- end