rotp 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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