From a0c5b909732b01ecdaf14a64f427c25181f267d9 Mon Sep 17 00:00:00 2001 From: Rodots Date: Mon, 3 Aug 2026 14:21:07 +0800 Subject: [PATCH 1/2] fix(security): validate code length range (6-8) --- src/GoogleAuthenticator.php | 8 +++++++- tests/GoogleAuthenticatorTest.php | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/GoogleAuthenticator.php b/src/GoogleAuthenticator.php index 59b5eda..e919511 100644 --- a/src/GoogleAuthenticator.php +++ b/src/GoogleAuthenticator.php @@ -5,6 +5,7 @@ use Endroid\QrCode\Builder\Builder; use Endroid\QrCode\Writer\PngWriter; use Exception; +use InvalidArgumentException; use Vectorface\OtpAuth\Base32; use Vectorface\OtpAuth\UriBuilder; @@ -163,10 +164,15 @@ public function verifyCode(string $secret, string $code, int $discrepancy = 1) : } /** - * Set the code length, should be >=6 + * Set the code length, must be between 6 and 8 (RFC 4226) + * + * @throws InvalidArgumentException */ public function setCodeLength(int $length) : self { + if ($length < 6 || $length > 8) { + throw new InvalidArgumentException('Code length must be between 6 and 8'); + } $this->_codeLength = $length; return $this; } diff --git a/tests/GoogleAuthenticatorTest.php b/tests/GoogleAuthenticatorTest.php index f642650..1befb85 100644 --- a/tests/GoogleAuthenticatorTest.php +++ b/tests/GoogleAuthenticatorTest.php @@ -3,6 +3,7 @@ namespace Tests\Vectorface; use Exception; +use InvalidArgumentException; use PHPUnit\Framework\TestCase; use Vectorface\GoogleAuthenticator; use Vectorface\OtpAuth\Parameters\Algorithm; @@ -170,6 +171,28 @@ public function testSetCodeLength() $this->assertInstanceOf(GoogleAuthenticator::class, $result); } + public function invalidCodeLengthProvider() + { + return [ + 'Too short' => [5], + 'Too long' => [9], + 'Zero' => [0], + 'Negative' => [-1], + ]; + } + + /** + * @dataProvider invalidCodeLengthProvider + * @param int $length + */ + public function testSetCodeLengthRejectsOutOfRangeValues(int $length) + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Code length must be between 6 and 8'); + + $this->googleAuthenticator->setCodeLength($length); + } + public function badSecretProvider() { return [ From c302d60f8f21f2242912e9d2e4e4f625ee5d7e66 Mon Sep 17 00:00:00 2001 From: Rodots Date: Mon, 3 Aug 2026 14:22:49 +0800 Subject: [PATCH 2/2] fix(security): verify code length against configured digits and require numeric codes --- src/GoogleAuthenticator.php | 2 +- tests/GoogleAuthenticatorTest.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/GoogleAuthenticator.php b/src/GoogleAuthenticator.php index e919511..5741e68 100644 --- a/src/GoogleAuthenticator.php +++ b/src/GoogleAuthenticator.php @@ -144,7 +144,7 @@ public function verifyCode(string $secret, string $code, int $discrepancy = 1) : { $currentTimeSlice = floor(time() / 30); - if (strlen($code) != 6) { + if (strlen($code) !== $this->_codeLength || !ctype_digit($code)) { return false; } diff --git a/tests/GoogleAuthenticatorTest.php b/tests/GoogleAuthenticatorTest.php index 1befb85..7fec11a 100644 --- a/tests/GoogleAuthenticatorTest.php +++ b/tests/GoogleAuthenticatorTest.php @@ -164,6 +164,34 @@ public function testVerifyCodeWithLeadingZero() $this->assertEquals(false, $result); } + /** + * @throws Exception + */ + public function testVerifyCodeWithEightDigits() + { + $secret = 'SECRET'; + $ga = $this->googleAuthenticator->setCodeLength(8); + + $code = $ga->getCode($secret); + $this->assertEquals(8, strlen($code)); + $this->assertTrue($ga->verifyCode($secret, $code)); + + // A 6-digit code must not verify when 8 digits are configured + $this->assertFalse($ga->verifyCode($secret, substr($code, 0, 6))); + } + + /** + * @throws Exception + */ + public function testVerifyCodeRejectsNonNumericCode() + { + $secret = 'SECRET'; + + $this->assertFalse($this->googleAuthenticator->verifyCode($secret, 'abcdef')); + $this->assertFalse($this->googleAuthenticator->verifyCode($secret, '12345x')); + $this->assertFalse($this->googleAuthenticator->verifyCode($secret, "12345\n")); + } + public function testSetCodeLength() { $result = $this->googleAuthenticator->setCodeLength(6);