Skip to content

Commit a82e464

Browse files
committed
Add Cryptex
1 parent d26ab7c commit a82e464

File tree

4 files changed

+187
-0
lines changed

4 files changed

+187
-0
lines changed

src/Nexus/Encryption/Cryptex.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Encryption;
15+
16+
use Nexus\Encryption\Exception\InvalidEncodingVariantException;
17+
18+
final readonly class Cryptex
19+
{
20+
/**
21+
* Version tag in the form 'v' + major + minor + patch.
22+
*
23+
* Note: Increment only the major and minor versions when making updates.
24+
*/
25+
public const string HEADER_VERSION = "\x76\x01\x00\x00";
26+
27+
/**
28+
* Length of the version header.
29+
*/
30+
public const int HEADER_VERSION_SIZE = 4;
31+
32+
public const int ENCODE_NONE = 0;
33+
public const int ENCODE_BASE64_ORIGINAL = 1;
34+
public const int ENCODE_BASE64_ORIGINAL_NO_PADDING = 2;
35+
public const int ENCODE_BASE64_URL_SAFE = 3;
36+
public const int ENCODE_BASE64_URL_SAFE_NO_PADDING = 4;
37+
public const int ENCODE_HEX = 5;
38+
39+
/**
40+
* Gets the encoder. If `self::ENCODE_NONE` is chosen, any subsequent encode
41+
* and decode operations will just return the strings as-is.
42+
*
43+
* @throws InvalidEncodingVariantException
44+
*/
45+
public static function encoder(int $variant = self::ENCODE_HEX): Encoding\EncoderInterface
46+
{
47+
return match ($variant) {
48+
self::ENCODE_NONE => new Encoding\NullEncoder(),
49+
self::ENCODE_BASE64_ORIGINAL => new Encoding\Base64OriginalEncoder(),
50+
self::ENCODE_BASE64_ORIGINAL_NO_PADDING => new Encoding\Base64OriginalNoPaddingEncoder(),
51+
self::ENCODE_BASE64_URL_SAFE => new Encoding\Base64UrlSafeEncoder(),
52+
self::ENCODE_BASE64_URL_SAFE_NO_PADDING => new Encoding\Base64UrlSafeNoPaddingEncoder(),
53+
self::ENCODE_HEX => new Encoding\HexEncoder(),
54+
default => throw new InvalidEncodingVariantException(),
55+
};
56+
}
57+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Encryption\Exception;
15+
16+
final class InvalidEncodingVariantException extends \RuntimeException
17+
{
18+
public function __construct()
19+
{
20+
parent::__construct('Unknown variant for encoder.');
21+
}
22+
}

tests/Encryption/CryptexTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Tests\Encryption;
15+
16+
use Nexus\Encryption\Cryptex;
17+
use Nexus\Encryption\Encoding\Base64OriginalEncoder;
18+
use Nexus\Encryption\Encoding\Base64OriginalNoPaddingEncoder;
19+
use Nexus\Encryption\Encoding\Base64UrlSafeEncoder;
20+
use Nexus\Encryption\Encoding\Base64UrlSafeNoPaddingEncoder;
21+
use Nexus\Encryption\Encoding\EncoderInterface;
22+
use Nexus\Encryption\Encoding\HexEncoder;
23+
use Nexus\Encryption\Encoding\NullEncoder;
24+
use Nexus\Encryption\Exception\InvalidEncodingVariantException;
25+
use PHPUnit\Framework\Attributes\CoversClass;
26+
use PHPUnit\Framework\Attributes\DataProvider;
27+
use PHPUnit\Framework\Attributes\Group;
28+
use PHPUnit\Framework\TestCase;
29+
30+
/**
31+
* @internal
32+
*/
33+
#[CoversClass(Cryptex::class)]
34+
#[Group('unit-test')]
35+
final class CryptexTest extends TestCase
36+
{
37+
public function testInvalidVariantThrows(): void
38+
{
39+
$this->expectException(InvalidEncodingVariantException::class);
40+
$this->expectExceptionMessage('Unknown variant for encoder.');
41+
42+
Cryptex::encoder(10);
43+
}
44+
45+
/**
46+
* @param class-string<EncoderInterface> $expectedEncoder
47+
*/
48+
#[DataProvider('provideEncoderCases')]
49+
public function testEncoder(int $variant, string $expectedEncoder): void
50+
{
51+
self::assertInstanceOf($expectedEncoder, Cryptex::encoder($variant));
52+
}
53+
54+
/**
55+
* @return iterable<string, array{int, class-string<EncoderInterface>}>
56+
*/
57+
public static function provideEncoderCases(): iterable
58+
{
59+
yield 'base64 original' => [Cryptex::ENCODE_BASE64_ORIGINAL, Base64OriginalEncoder::class];
60+
61+
yield 'base 64 original no padding' => [Cryptex::ENCODE_BASE64_ORIGINAL_NO_PADDING, Base64OriginalNoPaddingEncoder::class];
62+
63+
yield 'base 64 URL safe' => [Cryptex::ENCODE_BASE64_URL_SAFE, Base64UrlSafeEncoder::class];
64+
65+
yield 'base 64 URL safe no padding' => [Cryptex::ENCODE_BASE64_URL_SAFE_NO_PADDING, Base64UrlSafeNoPaddingEncoder::class];
66+
67+
yield 'hex' => [Cryptex::ENCODE_HEX, HexEncoder::class];
68+
69+
yield 'none' => [Cryptex::ENCODE_NONE, NullEncoder::class];
70+
}
71+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* This file is part of the Nexus framework.
7+
*
8+
* (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9+
*
10+
* For the full copyright and license information, please view
11+
* the LICENSE file that was distributed with this source code.
12+
*/
13+
14+
namespace Nexus\Tests\Encryption\Exception;
15+
16+
use Nexus\Encryption\Cryptex;
17+
use Nexus\Encryption\Exception\InvalidEncodingVariantException;
18+
use PHPUnit\Framework\Attributes\CoversClass;
19+
use PHPUnit\Framework\Attributes\Group;
20+
use PHPUnit\Framework\TestCase;
21+
22+
/**
23+
* @internal
24+
*/
25+
#[CoversClass(InvalidEncodingVariantException::class)]
26+
#[Group('unit-test')]
27+
final class InvalidEncodingVariantExceptionTest extends TestCase
28+
{
29+
public function testMessage(): void
30+
{
31+
try {
32+
Cryptex::encoder(10);
33+
} catch (InvalidEncodingVariantException $e) {
34+
self::assertSame('Unknown variant for encoder.', $e->getMessage());
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)