rotp 3.1.0 → 3.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/rotp/totp.rb +24 -0
- data/lib/rotp/version.rb +1 -1
- data/spec/lib/rotp/totp_spec.rb +112 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e81c60dc4a476ab617e914fe50d3739290e9a110
|
4
|
+
data.tar.gz: 3f99b3ec451c23b615ff7a58acbcf5a105f5f5c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f2ad34ca1702d72edb5e16dd715d58f6980c4412577cc40cd5337f6f3cb21958345883e4e67573eaf540364fecf4d9e73a720c4a79042327c2ac6d7e8f6bbbd
|
7
|
+
data.tar.gz: ad3ddffe067a7716d6cfaadcc7c9e8ac256831efc7d6214d7422269d4805eed427161af4f0c1de773ebe386d93355d495551aba03498a61e9277d3377ac1cdc1
|
data/CHANGELOG.md
CHANGED
data/lib/rotp/totp.rb
CHANGED
@@ -47,6 +47,30 @@ module ROTP
|
|
47
47
|
times.any? { |ti| verify(otp, ti) }
|
48
48
|
end
|
49
49
|
|
50
|
+
# Verifies the OTP passed in against the current time OTP
|
51
|
+
# and adjacent intervals up to +drift+. Excludes OTPs
|
52
|
+
# from prior_time and earlier. Returns time value of
|
53
|
+
# matching OTP code for use in subsequent call.
|
54
|
+
# @param [String] otp the OTP to check against
|
55
|
+
# @param [Integer] drift the number of seconds that the client
|
56
|
+
# and server are allowed to drift apart
|
57
|
+
# @param [Integer] time value of previous match
|
58
|
+
def verify_with_drift_and_prior(otp, drift, prior_time = nil, time = Time.now)
|
59
|
+
# calculate normalized bin start times based on drift
|
60
|
+
first_bin = (time - drift).to_i / interval * interval
|
61
|
+
last_bin = (time + drift).to_i / interval * interval
|
62
|
+
|
63
|
+
# if prior_time was supplied, adjust first bin if necessary to exclude it
|
64
|
+
if prior_time
|
65
|
+
prior_bin = prior_time.to_i / interval * interval
|
66
|
+
first_bin = prior_bin + interval if prior_bin >= first_bin
|
67
|
+
# fail if we've already used the last available OTP code
|
68
|
+
return if first_bin > last_bin
|
69
|
+
end
|
70
|
+
times = (first_bin..last_bin).step(interval).to_a
|
71
|
+
times.find { |ti| verify(otp, ti) }
|
72
|
+
end
|
73
|
+
|
50
74
|
# Returns the provisioning URI for the OTP
|
51
75
|
# This can then be encoded in a QR Code and used
|
52
76
|
# to provision the Google Authenticator app
|
data/lib/rotp/version.rb
CHANGED
data/spec/lib/rotp/totp_spec.rb
CHANGED
@@ -222,6 +222,118 @@ RSpec.describe ROTP::TOTP do
|
|
222
222
|
end
|
223
223
|
end
|
224
224
|
|
225
|
+
describe '#verify_with_drift_and_prior' do
|
226
|
+
let(:verification) { totp.verify_with_drift_and_prior token, drift, prior, now }
|
227
|
+
let(:drift) { 0 }
|
228
|
+
let(:prior) { nil }
|
229
|
+
|
230
|
+
context 'numeric token' do
|
231
|
+
let(:token) { 68212 }
|
232
|
+
|
233
|
+
it 'raises an error' do
|
234
|
+
# In the "old" specs this was not tested due to a typo. What is the expected behavior here?
|
235
|
+
expect { verification }.to raise_error
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'unpadded string token' do
|
240
|
+
let(:token) { '68212' }
|
241
|
+
|
242
|
+
it 'is false' do
|
243
|
+
# Not sure whether this should be tested. It didn't exist in the "old" specs
|
244
|
+
expect(verification).to be_falsey
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'correctly padded string token' do
|
249
|
+
let(:token) { '068212' }
|
250
|
+
|
251
|
+
it 'is true' do
|
252
|
+
expect(verification).to be_truthy
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context 'slightly old number' do
|
257
|
+
let(:token) { totp.at now - 30 }
|
258
|
+
let(:drift) { 60 }
|
259
|
+
|
260
|
+
it 'is true' do
|
261
|
+
expect(verification).to be_truthy
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
context 'slightly new number' do
|
266
|
+
let(:token) { totp.at now + 60 }
|
267
|
+
let(:drift) { 60 }
|
268
|
+
|
269
|
+
it 'is true' do
|
270
|
+
expect(verification).to be_truthy
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'outside of drift range' do
|
275
|
+
let(:token) { totp.at now - 60 }
|
276
|
+
let(:drift) { 30 }
|
277
|
+
|
278
|
+
it 'is false' do
|
279
|
+
expect(verification).to be_falsey
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'drift is not multiple of TOTP interval' do
|
284
|
+
context 'slightly old number' do
|
285
|
+
let(:token) { totp.at now - 45 }
|
286
|
+
let(:drift) { 45 }
|
287
|
+
|
288
|
+
it 'is true' do
|
289
|
+
expect(verification).to be_truthy
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context 'slightly new number' do
|
294
|
+
let(:token) { totp.at now + 40 }
|
295
|
+
let(:drift) { 40 }
|
296
|
+
|
297
|
+
it 'is true' do
|
298
|
+
expect(verification).to be_truthy
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'with a prior verify' do
|
304
|
+
let(:prior) { totp.verify_with_drift_and_prior '068212', 0, nil, now }
|
305
|
+
|
306
|
+
it 'returns a timecode' do
|
307
|
+
expect(prior).to be_within(30).of(now.to_i)
|
308
|
+
end
|
309
|
+
|
310
|
+
context 'reusing same token' do
|
311
|
+
|
312
|
+
it 'is false' do
|
313
|
+
expect(verification).to be_falsy
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
context 'newer token' do
|
318
|
+
let(:token) { totp.at now + 40 }
|
319
|
+
let(:drift) { 40 }
|
320
|
+
|
321
|
+
it 'is true' do
|
322
|
+
expect(verification).to be_truthy
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
context 'older token' do
|
327
|
+
let(:token) { totp.at now - 40 }
|
328
|
+
let(:drift) { 40 }
|
329
|
+
|
330
|
+
it 'is false' do
|
331
|
+
expect(verification).to be_falsy
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
225
337
|
describe '#now' do
|
226
338
|
before do
|
227
339
|
Timecop.freeze now
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rotp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.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: 2016-
|
11
|
+
date: 2016-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: guard-rspec
|