Skip to content

Commit 30140c1

Browse files
committed
OXDEV-9078 Add code generator and hasher
1 parent 5c22fb2 commit 30140c1

6 files changed

Lines changed: 172 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
class OtpCodeGeneratorService implements OtpCodeGeneratorServiceInterface
13+
{
14+
public function generateCode(): string
15+
{
16+
// todo-low: length from settings
17+
$length = 6;
18+
19+
return str_pad((string) random_int(0, 999999), $length, '0', STR_PAD_LEFT);
20+
}
21+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
interface OtpCodeGeneratorServiceInterface
13+
{
14+
public function generateCode(): string;
15+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
class OtpCodeHasherService implements OtpCodeHasherServiceInterface
13+
{
14+
public function hash(#[\SensitiveParameter] string $code): string
15+
{
16+
return hash('sha256', $code);
17+
}
18+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
interface OtpCodeHasherServiceInterface
13+
{
14+
public function hash(#[\SensitiveParameter] string $code): string;
15+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Tests\Unit\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeGeneratorService;
13+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeGeneratorServiceInterface;
14+
use PHPUnit\Framework\Attributes\Test;
15+
use PHPUnit\Framework\TestCase;
16+
17+
class OtpCodeGeneratorServiceTest extends TestCase
18+
{
19+
#[Test]
20+
public function generateReturnsNumericString(): void
21+
{
22+
$sut = $this->getSut();
23+
24+
$result = $sut->generateCode();
25+
26+
$this->assertMatchesRegularExpression('/^\d+$/', $result);
27+
}
28+
29+
#[Test]
30+
public function generateReturnsSpecificLengthCode(): void
31+
{
32+
$expectedLength = 6;
33+
34+
$sut = $this->getSut();
35+
36+
$result = $sut->generateCode();
37+
38+
$this->assertSame($expectedLength, strlen($result));
39+
}
40+
41+
#[Test]
42+
public function generateReturnsDifferentCodesOnSubsequentCalls(): void
43+
{
44+
$sut = $this->getSut();
45+
46+
$this->assertNotSame($sut->generateCode(), $sut->generateCode());
47+
}
48+
49+
private function getSut(): OtpCodeGeneratorServiceInterface
50+
{
51+
return new OtpCodeGeneratorService();
52+
}
53+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/**
4+
* Copyright © OXID eSales AG. All rights reserved.
5+
* See LICENSE file for license details.
6+
*/
7+
8+
declare(strict_types=1);
9+
10+
namespace OxidEsales\SecurityModule\Tests\Unit\Authentication\TwoFactorAuth\OTP\Service;
11+
12+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeHasherService;
13+
use OxidEsales\SecurityModule\Authentication\TwoFactorAuth\OTP\Service\OtpCodeHasherServiceInterface;
14+
use PHPUnit\Framework\Attributes\Test;
15+
use PHPUnit\Framework\TestCase;
16+
17+
class OtpCodeHasherServiceTest extends TestCase
18+
{
19+
#[Test]
20+
public function hashReturnsDifferentValueThanInput(): void
21+
{
22+
$sut = $this->getSut();
23+
24+
$result = $sut->hash(code: $code = uniqid());
25+
26+
$this->assertNotSame($code, $result);
27+
}
28+
29+
#[Test]
30+
public function hashReturnsSameResultForSameInput(): void
31+
{
32+
$sut = $this->getSut();
33+
$code = uniqid();
34+
35+
$this->assertSame($sut->hash(code: $code), $sut->hash(code: $code));
36+
}
37+
38+
#[Test]
39+
public function hashReturnsDifferentResultForDifferentInput(): void
40+
{
41+
$sut = $this->getSut();
42+
43+
$this->assertNotSame($sut->hash(code: uniqid()), $sut->hash(code: uniqid()));
44+
}
45+
46+
private function getSut(): OtpCodeHasherServiceInterface
47+
{
48+
return new OtpCodeHasherService();
49+
}
50+
}

0 commit comments

Comments
 (0)