Skip to content

Implement Nexus Encryption v2 #8

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

Draft
wants to merge 11 commits into
base: 1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"replace": {
"nexusphp/clock": "self.version",
"nexusphp/collection": "self.version",
"nexusphp/encryption": "self.version",
"nexusphp/option": "self.version",
"nexusphp/password": "self.version",
"nexusphp/phpstan-nexus": "self.version",
Expand Down
7 changes: 5 additions & 2 deletions infection.json5
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@
"LogicalOrAllSubExprNegation": true,
"LogicalOrNegation": true,
"LogicalOrSingleSubExprNegation": true,
"MBString": true,
"MatchArmRemoval": true,
"MethodCallRemoval": true,
"MinusEqual": true,
Expand Down Expand Up @@ -145,7 +144,11 @@
"SpreadRemoval": true,
"Ternary": true,
"This": true,
"Throw_": true,
"Throw_": {
"ignore": [
"Nexus\\Encryption\\Key::__unserialize"
]
},
"TrueValue": {
"ignore": [
"Nexus\\Collection\\Collection::generateDiffHashTable"
Expand Down
53 changes: 53 additions & 0 deletions src/Nexus/Clock/Extension/ClockAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Clock\Extension;

use Nexus\Clock\Clock;
use Nexus\Clock\FrozenClock;
use Nexus\Clock\SystemClock;
use Psr\Clock\ClockInterface;

/**
* A trait to help write time-sensitive classes.
*
* @phpstan-require-implements ClockAwareInterface
*/
trait ClockAware
{
private ?Clock $clock = null;

public function setClock(?ClockInterface $clock): self
{
if (null !== $clock && ! $clock instanceof Clock) {
$clock = new FrozenClock($clock->now());
}

$this->clock = $clock;

return $this;
}

public function getClock(): Clock
{
return $this->clock ?? new SystemClock('UTC');
}

/**
* Gets the current timestamp.
*/
private function now(): int
{
return $this->getClock()->now()->getTimestamp();
}
}
35 changes: 35 additions & 0 deletions src/Nexus/Clock/Extension/ClockAwareInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Clock\Extension;

use Nexus\Clock\Clock;
use Psr\Clock\ClockInterface;

/**
* Interface for mutable classes that require access to a clock.
*/
interface ClockAwareInterface
{
/**
* Sets the clock instance on the class. If the clock is not an instance of
* `Nexus\Clock\Clock`, it will be wrapped in a `Nexus\Clock\FrozenClock`.
* If `null` is passed, the class will use a `Nexus\Clock\SystemClock`.
*/
public function setClock(?ClockInterface $clock): self;

/**
* Gets the clock instance.
*/
public function getClock(): Clock;
}
35 changes: 35 additions & 0 deletions src/Nexus/Clock/Extension/ImmutableClockAware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Clock\Extension;

use Nexus\Clock\Clock;

/**
* A trait to help write time-sensitive immutable classes.
*
* Using classes must ensure that a readonly `Clock` instance is already
* injected into the class, preferably in the constructor.
*
* @property Clock $clock
*/
trait ImmutableClockAware
{
/**
* Gets the current timestamp.
*/
private function now(): int
{
return $this->clock->now()->getTimestamp();
}
}
36 changes: 36 additions & 0 deletions src/Nexus/Encryption/BinaryStr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption;

/**
* Binary string operations wrapping on related `mb_*` functions.
*/
final class BinaryStr
{
/**
* Get the length of a binary string.
*/
public static function strlen(#[\SensitiveParameter] string $string): int
{
return mb_strlen($string, '8bit');
}

/**
* Get a substring of a binary string.
*/
public static function substr(#[\SensitiveParameter] string $string, int $start, ?int $length = null): string
{
return mb_substr($string, $start, $length, '8bit');
}
}
57 changes: 57 additions & 0 deletions src/Nexus/Encryption/Cryptex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption;

use Nexus\Encryption\Exception\InvalidEncodingVariantException;

final readonly class Cryptex
{
/**
* Version tag in the form 'v' + major + minor + patch.
*
* Note: Increment only the major and minor versions when making updates.
*/
public const string HEADER_VERSION = "\x76\x01\x00\x00";

/**
* Length of the version header.
*/
public const int HEADER_VERSION_SIZE = 4;

public const int ENCODE_NONE = 0;
public const int ENCODE_BASE64_ORIGINAL = 1;
public const int ENCODE_BASE64_ORIGINAL_NO_PADDING = 2;
public const int ENCODE_BASE64_URL_SAFE = 3;
public const int ENCODE_BASE64_URL_SAFE_NO_PADDING = 4;
public const int ENCODE_HEX = 5;

/**
* Gets the encoder. If `self::ENCODE_NONE` is chosen, any subsequent encode
* and decode operations will just return the strings as-is.
*
* @throws InvalidEncodingVariantException
*/
public static function encoder(int $variant = self::ENCODE_HEX): Encoding\EncoderInterface
{
return match ($variant) {
self::ENCODE_NONE => new Encoding\NullEncoder(),
self::ENCODE_BASE64_ORIGINAL => new Encoding\Base64OriginalEncoder(),
self::ENCODE_BASE64_ORIGINAL_NO_PADDING => new Encoding\Base64OriginalNoPaddingEncoder(),
self::ENCODE_BASE64_URL_SAFE => new Encoding\Base64UrlSafeEncoder(),
self::ENCODE_BASE64_URL_SAFE_NO_PADDING => new Encoding\Base64UrlSafeNoPaddingEncoder(),
self::ENCODE_HEX => new Encoding\HexEncoder(),
default => throw new InvalidEncodingVariantException(),
};
}
}
32 changes: 32 additions & 0 deletions src/Nexus/Encryption/Encoding/AbstractBase64Encoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption\Encoding;

abstract class AbstractBase64Encoder implements EncoderInterface
{
public function encode(#[\SensitiveParameter] string $binaryString): string
{
return sodium_bin2base64($binaryString, $this->getBase64Variant());
}

public function decode(#[\SensitiveParameter] string $encodedString, string $ignore = ''): string
{
return sodium_base642bin($encodedString, $this->getBase64Variant(), $ignore);
}

/**
* Get the variant of Base64 encoding to use.
*/
abstract protected function getBase64Variant(): int;
}
25 changes: 25 additions & 0 deletions src/Nexus/Encryption/Encoding/Base64OriginalEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption\Encoding;

/**
* Standard (A-Za-z0-9/\+) Base64 encoder.
*/
final class Base64OriginalEncoder extends AbstractBase64Encoder
{
protected function getBase64Variant(): int
{
return SODIUM_BASE64_VARIANT_ORIGINAL;
}
}
25 changes: 25 additions & 0 deletions src/Nexus/Encryption/Encoding/Base64OriginalNoPaddingEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption\Encoding;

/**
* Standard (A-Za-z0-9/\+) Base64 encoder without `=` padding characters.
*/
final class Base64OriginalNoPaddingEncoder extends AbstractBase64Encoder
{
protected function getBase64Variant(): int
{
return SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING;
}
}
25 changes: 25 additions & 0 deletions src/Nexus/Encryption/Encoding/Base64UrlSafeEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption\Encoding;

/**
* URL-safe (A-Za-z0-9\-_) Base64 encoder.
*/
final class Base64UrlSafeEncoder extends AbstractBase64Encoder
{
protected function getBase64Variant(): int
{
return SODIUM_BASE64_VARIANT_URLSAFE;
}
}
25 changes: 25 additions & 0 deletions src/Nexus/Encryption/Encoding/Base64UrlSafeNoPaddingEncoder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

/**
* This file is part of the Nexus framework.
*
* (c) John Paul E. Balandan, CPA <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace Nexus\Encryption\Encoding;

/**
* URL-safe (A-Za-z0-9\-_) Base64 encoder, without `=` padding characters.
*/
final class Base64UrlSafeNoPaddingEncoder extends AbstractBase64Encoder
{
protected function getBase64Variant(): int
{
return SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING;
}
}
Loading
Loading