rotp 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c450bbb03ba621504bffd4d10d86beb9aa0df214
4
- data.tar.gz: 13a046cf63204bea4517283ae0a2473becc67ceb
3
+ metadata.gz: e81c60dc4a476ab617e914fe50d3739290e9a110
4
+ data.tar.gz: 3f99b3ec451c23b615ff7a58acbcf5a105f5f5c3
5
5
  SHA512:
6
- metadata.gz: d76a02cc91e2de40619a99a925c3452546c31914fc0172918c40a68f405975b6ee293f437d91d49004b1e4074607f9f7abf8b266345ced389e9e313d6f0ab030
7
- data.tar.gz: 08e82ddf0a585ee225a9d98b04cf0a22c7a386504f8f3db3936c07dc6231ecafa3f8f920fd9048b4606cb14080a194f7a4c333311735696d9016a88975d0c5b1
6
+ metadata.gz: 0f2ad34ca1702d72edb5e16dd715d58f6980c4412577cc40cd5337f6f3cb21958345883e4e67573eaf540364fecf4d9e73a720c4a79042327c2ac6d7e8f6bbbd
7
+ data.tar.gz: ad3ddffe067a7716d6cfaadcc7c9e8ac256831efc7d6214d7422269d4805eed427161af4f0c1de773ebe386d93355d495551aba03498a61e9277d3377ac1cdc1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ### Changelog
2
2
 
3
+ #### 3.2.0
4
+
5
+ - Add 'verify_with_drift_and_prior' to prevent prior token use - #58 from @jlfaber
6
+
3
7
  #### 3.1.0
4
8
 
5
9
  - Add Add digits paramater to provisioning URI. #54 from @sbc100
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
@@ -1,3 +1,3 @@
1
1
  module ROTP
2
- VERSION = "3.1.0"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -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.1.0
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-06-14 00:00:00.000000000 Z
11
+ date: 2016-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: guard-rspec