Closed
Description
I have an issue where sometimes I generate a TOTP which is immediately invalid, even when I check against the previous time period. My understanding is that per the grace period doc if I use the same time, simple subtraction should allow my TOTP to pass.
Here is a test that demonstrates the problem:
Mix.install([:nimble_totp])
ExUnit.start()
defmodule Fixture do
@spec generate_totp(binary(), pos_integer()) :: binary()
def generate_totp(secret, period, time \\ System.os_time(:second)) do
NimbleTOTP.verification_code(secret, period: period, time: time)
end
@spec valid_totp?(binary(), binary(), integer()) :: boolean()
def valid_totp?(secret, totp, period, time \\ System.os_time(:second)) do
(NimbleTOTP.valid?(secret, totp, period: period, time: time) ||
NimbleTOTP.valid?(secret, totp, period: period, time: time - period))
|> if do
true
else
false
end
end
end
defmodule NimbleTOTPTest do
use ExUnit.Case
test "is valid within the period in which the totp was generated" do
time = System.os_time(:second)
totp = Fixture.generate_totp("abc123", 100, time)
assert Fixture.valid_totp?("abc123", totp, 100, time - 10)
end
test "is valid within the next time period following expiration" do
time = System.os_time(:second)
totp = Fixture.generate_totp("abc123", 100, time - 102)
assert Fixture.valid_totp?("abc123", totp, 100, time)
end
test "is invalid after two time periods" do
time = System.os_time(:second)
totp = Fixture.generate_totp("abc123", 100, time - 205)
refute Fixture.valid_totp?("abc123", totp, 100, time)
end
end
If I save that file as nimble_totp_test.exs
and run the following command:
while elixir -r nimble_totp_test.exs; do
echo
done
It seems like the only failures happen the time is divisible by 10.
1) test is valid within the period in which the totp was generated (NimbleTOTPTest)
nimble_totp_test.exs:25
Expected truthy, got false
code: assert Fixture.valid_totp?("abc123", totp, 100, time - 10)
arguments:
# 1
"abc123"
# 2
"537101"
# 3
100
# 4
1730929790
stacktrace:
nimble_totp_test.exs:28: (test)
2) test is valid within the next time period following expiration (NimbleTOTPTest)
nimble_totp_test.exs:31
Expected truthy, got false
code: assert Fixture.valid_totp?("abc123", totp, 100, time)
arguments:
# 1
"abc123"
# 2
"982784"
# 3
100
# 4
1730929800
stacktrace:
nimble_totp_test.exs:34: (test)
Metadata
Assignees
Labels
No labels