Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOTP -> verify doesn't seem to be correctly implemented to include leeway #162

Closed
aramhovsepyan opened this issue Aug 26, 2022 · 1 comment
Labels

Comments

@aramhovsepyan
Copy link

Version(s) affected

11.0

Description

Hi,
We've noticed that the latest implementation of the verify method in TOTP.php seems to be completely off. It should compare all possible otps between now and each period increment up to leeway. The current implementation only compares the current otp, the one +leeway and -leeway.
The presumably buggy code seems to appear in the 15Feb commit.

Apologies if I've missed something and thanks for the great work!

How to reproduce

Leeway = 4 used to work as +-4 periods before and after, now it works as +-4 seconds before and after.
PS: this makes it impossible to use a period of 30seconds and have a window of 1 minute extra.

Possible Solution

Bring back the old implementation.

Additional Context

No response

@Spomky
Copy link
Member

Spomky commented Aug 30, 2022

Hi,

Leeway = 4 used to work as +-4 periods before and after, now it works as +-4 seconds before and after.

This is correct. The behavior of the leeway parameter changed in v11. This has been introduced by #152.

PS: this makes it impossible to use a period of 30seconds and have a window of 1 minute extra.
This is right. This is actually the expected protection induced by this PR. The problem with the previous version is that it is easy to reduce the security of the OTP. With a window of 4, you divide by 9 the number of possibilities (4 periods before and after + the current period).

If you still need such flexibility, you have to implement it explicitly:

$window = abs($window);

for ($i = 0; $i <= $window; ++$i) {
    $next = $i * $this->getPeriod() + $timestamp;
    $previous = -$i * $this->getPeriod() + $timestamp;
    $valid = $this->compareOTP($this->at($next), $otp) ||
    $this->compareOTP($this->at($previous), $otp);

    if ($valid) {
        return true;
    }
}

return false;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants