Skip to content

Commit 5f0679e

Browse files
committedNov 1, 2018
Rubocop updates
- Autofix styling - Update to remove deprecated URI.encode in favor of Addressable's implementation
1 parent 957df8e commit 5f0679e

18 files changed

+120
-148
lines changed
 

‎Guardfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
guard :rspec, cmd: 'bundle exec rspec --format progress' do
2-
require "guard/rspec/dsl"
2+
require 'guard/rspec/dsl'
33
dsl = Guard::RSpec::Dsl.new(self)
44

55
# RSpec files

‎Rakefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
require 'bundler'
22
Bundler::GemHelper.install_tasks
3-
require "rspec/core/rake_task"
3+
require 'rspec/core/rake_task'
44

55
RSpec::Core::RakeTask.new(:rspec) do |spec|
66
spec.pattern = 'spec/**/*_spec.rb'
77
end
88

9-
task :default => :rspec
9+
task default: :rspec

‎bin/rotp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env ruby
22

3-
$: << File.expand_path('../../lib', __FILE__)
3+
$LOAD_PATH << File.expand_path('../lib', __dir__)
44
require 'rotp'
55
require 'rotp/cli'
66

‎lib/rotp.rb

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
require 'cgi'
2-
require 'uri'
2+
require 'addressable'
33
require 'securerandom'
44
require 'openssl'
55
require 'rotp/base32'
66
require 'rotp/otp'
77
require 'rotp/hotp'
88
require 'rotp/totp'
99

10-
1110
module ROTP
1211
end

‎lib/rotp/arguments.rb

+2-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
module ROTP
55
class Arguments
6-
76
def initialize(filename, arguments)
87
@filename = filename
98
@arguments = Array(arguments)
@@ -32,11 +31,11 @@ def default_options
3231

3332
def parse
3433
return options!.mode = :help if arguments.empty?
35-
parser.parse arguments
3634

35+
parser.parse arguments
3736
rescue OptionParser::InvalidOption => exception
3837
options!.mode = :help
39-
options!.warnings = red(exception.message + '. Try --help for help.')
38+
options!.warnings = red(exception.message + '. Try --help for help.')
4039
end
4140

4241
def parser
@@ -83,7 +82,5 @@ def green(string)
8382
def red(string)
8483
"\033[31m#{string}\033[0m"
8584
end
86-
8785
end
8886
end
89-

‎lib/rotp/base32.rb

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
module ROTP
22
class Base32
33
class Base32Error < RuntimeError; end
4-
CHARS = "abcdefghijklmnopqrstuvwxyz234567".each_char.to_a
4+
CHARS = 'abcdefghijklmnopqrstuvwxyz234567'.each_char.to_a
55

66
class << self
77
def decode(str)
8-
str = str.tr('=','')
8+
str = str.tr('=', '')
99
output = []
1010
str.scan(/.{1,8}/).each do |block|
11-
char_array = decode_block(block).map{|c| c.chr}
11+
char_array = decode_block(block).map(&:chr)
1212
output << char_array
1313
end
1414
output.join
1515
end
1616

17-
def random_base32(length=32)
18-
b32 = String.new
17+
def random_base32(length = 32)
18+
b32 = ''
1919
SecureRandom.random_bytes(length).each_byte do |b|
2020
b32 << CHARS[b % 32]
2121
end
@@ -26,25 +26,27 @@ def random_base32(length=32)
2626

2727
def decode_block(block)
2828
length = block.scan(/[^=]/).length
29-
quints = block.each_char.map {|c| decode_quint(c)}
29+
quints = block.each_char.map { |c| decode_quint(c) }
3030
bytes = []
3131
bytes[0] = (quints[0] << 3) + (quints[1] ? quints[1] >> 2 : 0)
3232
return bytes if length < 3
33+
3334
bytes[1] = ((quints[1] & 3) << 6) + (quints[2] << 1) + (quints[3] ? quints[3] >> 4 : 0)
3435
return bytes if length < 4
36+
3537
bytes[2] = ((quints[3] & 15) << 4) + (quints[4] ? quints[4] >> 1 : 0)
3638
return bytes if length < 6
39+
3740
bytes[3] = ((quints[4] & 1) << 7) + (quints[5] << 2) + (quints[6] ? quints[6] >> 3 : 0)
3841
return bytes if length < 7
42+
3943
bytes[4] = ((quints[6] & 7) << 5) + (quints[7] || 0)
4044
bytes
4145
end
4246

4347
def decode_quint(q)
44-
CHARS.index(q.downcase) or raise(Base32Error, "Invalid Base32 Character - '#{q}'")
48+
CHARS.index(q.downcase) || raise(Base32Error, "Invalid Base32 Character - '#{q}'")
4549
end
46-
4750
end
48-
4951
end
5052
end

‎lib/rotp/cli.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ def run
1616
# :nocov:
1717

1818
def errors
19-
if [:time, :hmac].include?(options.mode)
19+
if %i[time hmac].include?(options.mode)
2020
if options.secret.to_s == ''
2121
red 'You must also specify a --secret. Try --help for help.'
22-
elsif options.secret.to_s.chars.any? { |c| ROTP::Base32::CHARS.index(c.downcase) == nil }
22+
elsif options.secret.to_s.chars.any? { |c| ROTP::Base32::CHARS.index(c.downcase).nil? }
2323
red 'Secret must be in RFC4648 Base32 format - http://en.wikipedia.org/wiki/Base32#RFC_4648_Base32_alphabet'
2424
end
2525
end
@@ -48,6 +48,5 @@ def options
4848
def red(string)
4949
"\033[31m#{string}\033[0m"
5050
end
51-
5251
end
5352
end

‎lib/rotp/hotp.rb

+6-8
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ def at(count)
1212
# @param counter [Integer] the counter of the OTP
1313
# @param retries [Integer] number of counters to incrementally retry
1414
def verify(otp, counter, retries: 0)
15-
counters = (counter..counter+retries).to_a
16-
counters.find { |c|
17-
super(otp, self.at(c))
18-
}
15+
counters = (counter..counter + retries).to_a
16+
counters.find do |c|
17+
super(otp, at(c))
18+
end
1919
end
2020

2121
# Returns the provisioning URI for the OTP
@@ -24,15 +24,13 @@ def verify(otp, counter, retries: 0)
2424
# @param [String] name of the account
2525
# @param [Integer] initial_count starting counter value, defaults to 0
2626
# @return [String] provisioning uri
27-
def provisioning_uri(name, initial_count=0)
27+
def provisioning_uri(name, initial_count = 0)
2828
params = {
2929
secret: secret,
3030
counter: initial_count,
3131
digits: digits == DEFAULT_DIGITS ? nil : digits
3232
}
33-
encode_params("otpauth://hotp/#{URI.encode(name)}", params)
33+
encode_params("otpauth://hotp/#{Addressable::URI.escape(name)}", params)
3434
end
35-
3635
end
37-
3836
end

‎lib/rotp/otp.rb

+13-14
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class OTP
1313
# @returns [OTP] OTP instantiation
1414
def initialize(s, options = {})
1515
@digits = options[:digits] || DEFAULT_DIGITS
16-
@digest = options[:digest] || "sha1"
16+
@digest = options[:digest] || 'sha1'
1717
@secret = s
1818
end
1919

@@ -30,17 +30,18 @@ def generate_otp(input)
3030

3131
offset = hmac[-1].ord & 0xf
3232
code = (hmac[offset].ord & 0x7f) << 24 |
33-
(hmac[offset + 1].ord & 0xff) << 16 |
34-
(hmac[offset + 2].ord & 0xff) << 8 |
35-
(hmac[offset + 3].ord & 0xff)
36-
(code % 10 ** digits).to_s.rjust(digits, '0')
33+
(hmac[offset + 1].ord & 0xff) << 16 |
34+
(hmac[offset + 2].ord & 0xff) << 8 |
35+
(hmac[offset + 3].ord & 0xff)
36+
(code % 10**digits).to_s.rjust(digits, '0')
3737
end
3838

3939
private
4040

4141
def verify(input, generated)
42-
raise ArgumentError, "`otp` should be a String" unless
42+
raise ArgumentError, '`otp` should be a String' unless
4343
input.is_a?(String)
44+
4445
time_constant_compare(input, generated)
4546
end
4647

@@ -54,24 +55,22 @@ def byte_secret
5455
#
5556
def int_to_bytestring(int, padding = 8)
5657
unless int >= 0
57-
raise ArgumentError, "#int_to_bytestring requires a positive number"
58+
raise ArgumentError, '#int_to_bytestring requires a positive number'
5859
end
5960

6061
result = []
6162
until int == 0
6263
result << (int & 0xFF).chr
63-
int >>= 8
64+
int >>= 8
6465
end
6566
result.reverse.join.rjust(padding, 0.chr)
6667
end
6768

6869
# A very simple param encoder
6970
def encode_params(uri, params)
70-
params_str = String.new("?")
71-
params.each do |k,v|
72-
if v
73-
params_str << "#{k}=#{CGI::escape(v.to_s)}&"
74-
end
71+
params_str = String.new('?')
72+
params.each do |k, v|
73+
params_str << "#{k}=#{CGI.escape(v.to_s)}&" if v
7574
end
7675
params_str.chop!
7776
uri + params_str
@@ -80,11 +79,11 @@ def encode_params(uri, params)
8079
# constant-time compare the strings
8180
def time_constant_compare(a, b)
8281
return false if a.empty? || b.empty? || a.bytesize != b.bytesize
82+
8383
l = a.unpack "C#{a.bytesize}"
8484
res = 0
8585
b.each_byte { |byte| res |= byte ^ l.shift }
8686
res == 0
8787
end
88-
8988
end
9089
end

‎lib/rotp/totp.rb

+14-22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module ROTP
22
DEFAULT_INTERVAL = 30
33
class TOTP < OTP
4-
54
attr_reader :interval, :issuer
65

76
# @option options [Integer] interval (30) the time interval in seconds for OTP
@@ -21,7 +20,7 @@ def at(time)
2120

2221
# Generate the current time OTP
2322
# @return [Integer] the OTP as an integer
24-
def now()
23+
def now
2524
generate_otp(timecode(Time.now))
2625
end
2726

@@ -40,20 +39,15 @@ def now()
4039
def verify(otp, drift_ahead: 0, drift_behind: 0, after: nil, at: Time.now)
4140
timecodes = get_timecodes(at, drift_behind, drift_ahead)
4241

43-
if after
44-
timecodes = timecodes.select { |t| t > timecode(after) }
45-
end
42+
timecodes = timecodes.select { |t| t > timecode(after) } if after
4643

4744
result = nil
48-
timecodes.each { |t|
49-
if (super(otp, self.generate_otp(t)))
50-
result = t * interval
51-
end
52-
}
53-
return result
45+
timecodes.each do |t|
46+
result = t * interval if super(otp, generate_otp(t))
47+
end
48+
result
5449
end
5550

56-
5751
# Returns the provisioning URI for the OTP
5852
# This can then be encoded in a QR Code and used
5953
# to provision the Google Authenticator app
@@ -64,15 +58,15 @@ def provisioning_uri(name)
6458
# https://github.com/google/google-authenticator/wiki/Key-Uri-Format
6559
# For compatibility the issuer appears both before that account name and also in the
6660
# query string.
67-
issuer_string = issuer.nil? ? "" : "#{URI.encode(issuer)}:"
61+
issuer_string = issuer.nil? ? '' : "#{Addressable::URI.escape(issuer)}:"
6862
params = {
6963
secret: secret,
7064
period: interval == 30 ? nil : interval,
7165
issuer: issuer,
7266
digits: digits == DEFAULT_DIGITS ? nil : digits,
73-
algorithm: digest.upcase == 'SHA1' ? nil : digest.upcase,
67+
algorithm: digest.casecmp('SHA1').zero? ? nil : digest.upcase
7468
}
75-
encode_params("otpauth://totp/#{issuer_string}#{URI.encode(name)}", params)
69+
encode_params("otpauth://totp/#{issuer_string}#{Addressable::URI.escape(name)}", params)
7670
end
7771

7872
private
@@ -82,20 +76,18 @@ def get_timecodes(at, drift_behind, drift_ahead)
8276
now = timeint(at)
8377
timecode_start = timecode(now - drift_behind)
8478
timecode_end = timecode(now + drift_ahead)
85-
return (timecode_start..timecode_end).step(1).to_a
79+
(timecode_start..timecode_end).step(1).to_a
8680
end
8781

8882
# Ensure UTC int
8983
def timeint(time)
90-
unless time.class == Time
91-
return time.to_i
92-
end
93-
return time.utc.to_i
84+
return time.to_i unless time.class == Time
85+
86+
time.utc.to_i
9487
end
9588

9689
def timecode(time)
97-
return timeint(time) / interval
90+
timeint(time) / interval
9891
end
99-
10092
end
10193
end

‎lib/rotp/version.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module ROTP
2-
VERSION = "4.0.0"
2+
VERSION = '4.0.0'.freeze
33
end

‎rotp.gemspec

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
1-
# -*- encoding: utf-8 -*-
2-
require "./lib/rotp/version"
1+
require './lib/rotp/version'
32

43
Gem::Specification.new do |s|
5-
s.name = "rotp"
4+
s.name = 'rotp'
65
s.version = ROTP::VERSION
76
s.platform = Gem::Platform::RUBY
8-
s.license = "MIT"
9-
s.authors = ["Mark Percival"]
10-
s.email = ["mark@markpercival.us"]
11-
s.homepage = "http://github.com/mdp/rotp"
12-
s.summary = %q{A Ruby library for generating and verifying one time passwords}
13-
s.description = %q{Works for both HOTP and TOTP, and includes QR Code provisioning}
7+
s.license = 'MIT'
8+
s.authors = ['Mark Percival']
9+
s.email = ['mark@markpercival.us']
10+
s.homepage = 'http://github.com/mdp/rotp'
11+
s.summary = 'A Ruby library for generating and verifying one time passwords'
12+
s.description = 'Works for both HOTP and TOTP, and includes QR Code provisioning'
1413

15-
s.rubyforge_project = "rotp"
14+
s.rubyforge_project = 'rotp'
1615

1716
s.files = `git ls-files`.split("\n")
1817
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20-
s.require_paths = ["lib"]
18+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19+
s.require_paths = ['lib']
20+
21+
s.add_dependency 'addressable', '~> 2.5'
2122

2223
s.add_development_dependency 'rake', '~> 10.5'
2324
s.add_development_dependency 'rspec', '~> 3.5'
24-
s.add_development_dependency 'timecop', '~> 0.8'
2525
s.add_development_dependency 'simplecov', '~> 0.12'
26+
s.add_development_dependency 'timecop', '~> 0.8'
2627
end

‎spec/lib/rotp/arguments_spec.rb

+5-6
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
end
2525

2626
context 'unknown arguments' do
27-
let(:argv) { %w(--does-not-exist -xyz) }
27+
let(:argv) { %w[--does-not-exist -xyz] }
2828

2929
describe '#options' do
3030
it 'is in help mode' do
@@ -48,7 +48,7 @@
4848
end
4949

5050
context 'asking for help' do
51-
let(:argv) { %w(--help) }
51+
let(:argv) { %w[--help] }
5252

5353
describe '#options' do
5454
it 'is in help mode' do
@@ -58,7 +58,7 @@
5858
end
5959

6060
context 'generating a counter based secret' do
61-
let(:argv) { %w(--hmac --secret s3same) }
61+
let(:argv) { %w[--hmac --secret s3same] }
6262

6363
describe '#options' do
6464
it 'is in hmac mode' do
@@ -72,7 +72,7 @@
7272
end
7373

7474
context 'generating a counter based secret' do
75-
let(:argv) { %w(--time --secret s3same) }
75+
let(:argv) { %w[--time --secret s3same] }
7676

7777
describe '#options' do
7878
it 'is in hmac mode' do
@@ -86,7 +86,7 @@
8686
end
8787

8888
context 'generating a time based secret' do
89-
let(:argv) { %w(--secret s3same) }
89+
let(:argv) { %w[--secret s3same] }
9090

9191
describe '#options' do
9292
it 'is in time mode' do
@@ -98,5 +98,4 @@
9898
end
9999
end
100100
end
101-
102101
end

‎spec/lib/rotp/base32_spec.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
require 'spec_helper'
22

33
RSpec.describe ROTP::Base32 do
4-
54
describe '.random_base32' do
65
context 'without arguments' do
76
let(:base32) { ROTP::Base32.random_base32 }
@@ -10,8 +9,8 @@
109
expect(base32.length).to eq 32
1110
end
1211

13-
it 'is hexadecimal' do
14-
expect(base32).to match %r{\A[a-z2-7]+\z}
12+
it 'is base32 charset' do
13+
expect(base32).to match(/\A[a-z2-7]+\z/)
1514
end
1615
end
1716

‎spec/lib/rotp/cli_spec.rb

+6-7
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,49 @@
44
RSpec.describe ROTP::CLI do
55
let(:cli) { described_class.new('executable', argv) }
66
let(:output) { cli.output }
7-
let(:now) { Time.utc 2012,1,1 }
7+
let(:now) { Time.utc 2012, 1, 1 }
88

99
before do
1010
Timecop.freeze now
1111
end
1212

1313
context 'generating a TOTP' do
14-
let(:argv) { %w(--secret JBSWY3DPEHPK3PXP) }
14+
let(:argv) { %w[--secret JBSWY3DPEHPK3PXP] }
1515

1616
it 'prints the corresponding token' do
1717
expect(output).to eq '068212'
1818
end
1919
end
2020

2121
context 'generating a TOTP with no secret' do
22-
let(:argv) { %W(--time --secret) }
22+
let(:argv) { %w[--time --secret] }
2323

2424
it 'prints the corresponding token' do
2525
expect(output).to match 'You must also specify a --secret'
2626
end
2727
end
2828

2929
context 'generating a TOTP with bad base32 secret' do
30-
let(:argv) { %W(--time --secret #{'1' * 32}) }
30+
let(:argv) { %W[--time --secret #{'1' * 32}] }
3131

3232
it 'prints the corresponding token' do
3333
expect(output).to match 'Secret must be in RFC4648 Base32 format'
3434
end
3535
end
3636

3737
context 'trying to generate an unsupport type' do
38-
let(:argv) { %W(--notreal --secret #{'a' * 32}) }
38+
let(:argv) { %W[--notreal --secret #{'a' * 32}] }
3939

4040
it 'prints the corresponding token' do
4141
expect(output).to match 'invalid option: --notreal'
4242
end
4343
end
4444

4545
context 'generating a HOTP' do
46-
let(:argv) { %W(--hmac --secret #{'a' * 32} --counter 1234) }
46+
let(:argv) { %W[--hmac --secret #{'a' * 32} --counter 1234] }
4747

4848
it 'prints the corresponding token' do
4949
expect(output).to eq '161024'
5050
end
5151
end
52-
5352
end

‎spec/lib/rotp/hotp_spec.rb

+4-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
context 'invalid counter' do
1818
it 'raises an error' do
19-
expect { hotp.at(-123456) }.to raise_error(ArgumentError)
19+
expect { hotp.at(-123_456) }.to raise_error(ArgumentError)
2020
end
2121
end
2222

@@ -37,15 +37,14 @@
3737
expect(hotp.at(8)).to eq '399871'
3838
expect(hotp.at(9)).to eq '520489'
3939
end
40-
4140
end
4241
end
4342

4443
describe '#verify' do
4544
let(:verification) { hotp.verify token, counter }
4645

4746
context 'numeric token' do
48-
let(:token) { 161024 }
47+
let(:token) { 161_024 }
4948

5049
it 'raises an error' do
5150
expect { verification }.to raise_error(ArgumentError)
@@ -68,7 +67,7 @@
6867
end
6968
end
7069
describe 'with retries' do
71-
let(:verification) { hotp.verify token, counter, retries:retries }
70+
let(:verification) { hotp.verify token, counter, retries: retries }
7271

7372
context 'counter outside than retries' do
7473
let(:counter) { 1223 }
@@ -110,7 +109,7 @@
110109

111110
describe '#provisioning_uri' do
112111
let(:uri) { hotp.provisioning_uri('mark@percival') }
113-
let(:params) { CGI::parse URI::parse(uri).query }
112+
let(:params) { CGI.parse URI.parse(uri).query }
114113

115114
it 'has the correct format' do
116115
expect(uri).to match %r{\Aotpauth:\/\/hotp.+}
@@ -134,5 +133,4 @@
134133
end
135134
end
136135
end
137-
138136
end

‎spec/lib/rotp/totp_spec.rb

+34-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require 'spec_helper'
22

3-
TEST_TIME = Time.utc 2016,9,23,9 # 2016-09-23 09:00:00 UTC
4-
TEST_TOKEN = "082630"
3+
TEST_TIME = Time.utc 2016, 9, 23, 9 # 2016-09-23 09:00:00 UTC
4+
TEST_TOKEN = '082630'.freeze
55

66
RSpec.describe ROTP::TOTP do
77
let(:now) { TEST_TIME }
@@ -19,19 +19,18 @@
1919
let(:totp) { ROTP::TOTP.new('GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ') }
2020

2121
it 'matches the RFC documentation examples' do
22-
expect(totp.at 1111111111).to eq '050471'
23-
expect(totp.at 1234567890).to eq '005924'
24-
expect(totp.at 2000000000).to eq '279037'
22+
expect(totp.at(1_111_111_111)).to eq '050471'
23+
expect(totp.at(1_234_567_890)).to eq '005924'
24+
expect(totp.at(2_000_000_000)).to eq '279037'
2525
end
26-
2726
end
2827
end
2928

3029
describe '#verify' do
3130
let(:verification) { totp.verify token, at: now }
3231

3332
context 'numeric token' do
34-
let(:token) { 82630 }
33+
let(:token) { 82_630 }
3534

3635
it 'raises an error with an integer' do
3736
expect { verification }.to raise_error(ArgumentError)
@@ -53,15 +52,15 @@
5352
end
5453

5554
context 'RFC compatibility' do
56-
let(:totp) { ROTP::TOTP.new 'wrn3pqx5uqxqvnqr' }
55+
let(:totp) { ROTP::TOTP.new 'wrn3pqx5uqxqvnqr' }
5756

5857
before do
5958
Timecop.freeze now
6059
end
6160

6261
context 'correct time based OTP' do
6362
let(:token) { '102705' }
64-
let(:now) { Time.at 1297553958 }
63+
let(:now) { Time.at 1_297_553_958 }
6564

6665
it 'verifies' do
6766
expect(totp.verify('102705')).to be_truthy
@@ -75,17 +74,17 @@
7574
end
7675
end
7776
context 'invalidating reused tokens' do
78-
let(:verification) {
77+
let(:verification) do
7978
totp.verify token,
80-
after: after,
81-
at: now
82-
}
79+
after: after,
80+
at: now
81+
end
8382
let(:after) { nil }
8483

8584
context 'passing in the `after` timestamp' do
86-
let(:after) {
85+
let(:after) do
8786
totp.verify TEST_TOKEN, after: nil, at: now
88-
}
87+
end
8988

9089
it 'returns a timecode' do
9190
expect(after).to be_kind_of(Integer)
@@ -106,23 +105,23 @@ def get_timecodes(at, b, a)
106105
totp.send('get_timecodes', at, b, a)
107106
end
108107

109-
describe "drifting timecodes" do
108+
describe 'drifting timecodes' do
110109
it 'should get timecodes behind' do
111-
expect(get_timecodes(TEST_TIME+15, 15, 0)).to eq([49154040])
112-
expect(get_timecodes(TEST_TIME, 15, 0)).to eq([49154039, 49154040])
113-
expect(get_timecodes(TEST_TIME, 40, 0)).to eq([49154038, 49154039, 49154040])
114-
expect(get_timecodes(TEST_TIME, 90, 0)).to eq([49154037, 49154038, 49154039, 49154040])
110+
expect(get_timecodes(TEST_TIME + 15, 15, 0)).to eq([49_154_040])
111+
expect(get_timecodes(TEST_TIME, 15, 0)).to eq([49_154_039, 49_154_040])
112+
expect(get_timecodes(TEST_TIME, 40, 0)).to eq([49_154_038, 49_154_039, 49_154_040])
113+
expect(get_timecodes(TEST_TIME, 90, 0)).to eq([49_154_037, 49_154_038, 49_154_039, 49_154_040])
115114
end
116115
it 'should get timecodes ahead' do
117-
expect(get_timecodes(TEST_TIME, 0, 15)).to eq([49154040])
118-
expect(get_timecodes(TEST_TIME+15, 0, 15)).to eq([49154040, 49154041])
119-
expect(get_timecodes(TEST_TIME, 0, 30)).to eq([49154040, 49154041])
120-
expect(get_timecodes(TEST_TIME, 0, 70)).to eq([49154040, 49154041, 49154042])
121-
expect(get_timecodes(TEST_TIME, 0, 90)).to eq([49154040, 49154041, 49154042, 49154043])
116+
expect(get_timecodes(TEST_TIME, 0, 15)).to eq([49_154_040])
117+
expect(get_timecodes(TEST_TIME + 15, 0, 15)).to eq([49_154_040, 49_154_041])
118+
expect(get_timecodes(TEST_TIME, 0, 30)).to eq([49_154_040, 49_154_041])
119+
expect(get_timecodes(TEST_TIME, 0, 70)).to eq([49_154_040, 49_154_041, 49_154_042])
120+
expect(get_timecodes(TEST_TIME, 0, 90)).to eq([49_154_040, 49_154_041, 49_154_042, 49_154_043])
122121
end
123122
it 'should get timecodes behind and ahead' do
124-
expect(get_timecodes(TEST_TIME, 30, 30)).to eq([49154039, 49154040, 49154041])
125-
expect(get_timecodes(TEST_TIME, 60, 60)).to eq([49154038, 49154039, 49154040, 49154041, 49154042])
123+
expect(get_timecodes(TEST_TIME, 30, 30)).to eq([49_154_039, 49_154_040, 49_154_041])
124+
expect(get_timecodes(TEST_TIME, 60, 60)).to eq([49_154_038, 49_154_039, 49_154_040, 49_154_041, 49_154_042])
126125
end
127126
end
128127

@@ -131,7 +130,6 @@ def get_timecodes(at, b, a)
131130
let(:drift_ahead) { 0 }
132131
let(:drift_behind) { 0 }
133132

134-
135133
context 'with an old OTP' do
136134
let(:token) { totp.at TEST_TIME - 30 } # Previous token at 2016-09-23 08:59:30 UTC
137135
let(:drift_behind) { 15 }
@@ -151,7 +149,6 @@ def get_timecodes(at, b, a)
151149
expect(verification).to be_nil
152150
end
153151
end
154-
155152
end
156153

157154
context 'with a future OTP' do
@@ -166,14 +163,13 @@ def get_timecodes(at, b, a)
166163
# Tested at 2016-09-23 09:00:20 UTC, and with drift ahead to 2016-09-23 09:00:35 UTC
167164
# This would therefore include 2 intervals
168165
context 'inside of drift range' do
169-
let(:now) { TEST_TIME + 20 }
166+
let(:now) { TEST_TIME + 20 }
170167

171168
it 'is true' do
172169
expect(verification).to be_truthy
173170
end
174171
end
175172
end
176-
177173
end
178174

179175
describe '#verify with drift and prevent token reuse' do
@@ -183,7 +179,6 @@ def get_timecodes(at, b, a)
183179
let(:after) { nil }
184180

185181
context 'with the `after` timestamp set' do
186-
187182
context 'older token' do
188183
let(:token) { totp.at TEST_TIME - 30 }
189184
let(:drift_behind) { 15 }
@@ -194,14 +189,13 @@ def get_timecodes(at, b, a)
194189
end
195190

196191
context 'after it has been used' do
197-
let(:after) {
192+
let(:after) do
198193
totp.verify token, after: nil, at: now, drift_behind: drift_behind
199-
}
194+
end
200195
it 'is false' do
201196
expect(verification).to be_falsey
202197
end
203198
end
204-
205199
end
206200

207201
context 'newer token' do
@@ -215,21 +209,20 @@ def get_timecodes(at, b, a)
215209
end
216210

217211
context 'after it has been used' do
218-
let(:after) {
212+
let(:after) do
219213
totp.verify token, after: nil, at: now, drift_ahead: drift_ahead
220-
}
214+
end
221215
it 'is false' do
222216
expect(verification).to be_falsey
223217
end
224218
end
225-
226219
end
227220
end
228221
end
229222

230223
describe '#provisioning_uri' do
231224
let(:uri) { totp.provisioning_uri('mark@percival') }
232-
let(:params) { CGI::parse URI::parse(uri).query }
225+
let(:params) { CGI.parse URI.parse(uri).query }
233226

234227
context 'without issuer' do
235228
it 'has the correct format' do
@@ -302,7 +295,6 @@ def get_timecodes(at, b, a)
302295
expect(params['algorithm'].first).to eq 'SHA256'
303296
end
304297
end
305-
306298
end
307299

308300
describe '#now' do
@@ -312,7 +304,7 @@ def get_timecodes(at, b, a)
312304

313305
context 'Google Authenticator' do
314306
let(:totp) { ROTP::TOTP.new 'wrn3pqx5uqxqvnqr' }
315-
let(:now) { Time.at 1297553958 }
307+
let(:now) { Time.at 1_297_553_958 }
316308

317309
it 'matches the known output' do
318310
expect(totp.now).to eq '102705'
@@ -321,12 +313,11 @@ def get_timecodes(at, b, a)
321313

322314
context 'Dropbox 26 char secret output' do
323315
let(:totp) { ROTP::TOTP.new 'tjtpqea6a42l56g5eym73go2oa' }
324-
let(:now) { Time.at 1378762454 }
316+
let(:now) { Time.at 1_378_762_454 }
325317

326318
it 'matches the known output' do
327319
expect(totp.now).to eq '747864'
328320
end
329321
end
330322
end
331-
332323
end

‎spec/spec_helper.rb

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require 'simplecov'
22
SimpleCov.start do
3-
add_filter "/spec/"
3+
add_filter '/spec/'
44
end
55

66
require 'rotp'
@@ -17,5 +17,4 @@
1717
end
1818
end
1919

20-
2120
require_relative '../lib/rotp'

0 commit comments

Comments
 (0)
Please sign in to comment.