-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9b9209e
commit cd10d3a
Showing
2 changed files
with
150 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
<?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; | ||
|
||
abstract class Key | ||
{ | ||
private ?string $keyString; | ||
|
||
public function __construct(Secret $key) | ||
{ | ||
$this->keyString = $key->reveal(); | ||
} | ||
|
||
public function __destruct() | ||
{ | ||
sodium_memzero($this->keyString); | ||
} | ||
|
||
public function __clone(): void | ||
{ | ||
throw new \BadMethodCallException(\sprintf('Cannot clone a %s object.', basename(static::class))); | ||
} | ||
|
||
/** | ||
* @return array<string, string> | ||
*/ | ||
public function __debugInfo(): array | ||
{ | ||
return ['keyString' => '[redacted]']; | ||
} | ||
|
||
public function __serialize(): never | ||
{ | ||
throw new \BadMethodCallException(\sprintf('Cannot serialise a %s object.', static::class)); | ||
} | ||
|
||
/** | ||
* @param array<string, mixed> $data | ||
*/ | ||
public function __unserialize(array $data): never | ||
{ | ||
throw new \BadMethodCallException(\sprintf('Cannot unserialise a %s object.', static::class)); // @codeCoverageIgnore | ||
} | ||
|
||
public function getKeyString(): string | ||
{ | ||
return $this->keyString ?? ''; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?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\Tests\Encryption; | ||
|
||
use Nexus\Encryption\Key; | ||
use Nexus\Encryption\Secret; | ||
use PHPUnit\Framework\Attributes\CoversClass; | ||
use PHPUnit\Framework\Attributes\Group; | ||
use PHPUnit\Framework\MockObject\MockObject; | ||
use PHPUnit\Framework\TestCase; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
#[CoversClass(Key::class)] | ||
#[Group('unit-test')] | ||
final class KeyTest extends TestCase | ||
{ | ||
private Key&MockObject $key; | ||
|
||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
$this->key = $this->getMockBuilder(Key::class) | ||
->setConstructorArgs([new Secret(random_bytes(32))]) | ||
->onlyMethods([]) | ||
->getMock() | ||
; | ||
} | ||
|
||
public function testCannotCloneKey(): void | ||
{ | ||
$this->expectException(\BadMethodCallException::class); | ||
$this->expectExceptionMessage(\sprintf('Cannot clone a %s object.', \get_class($this->key))); | ||
|
||
clone $this->key; // @phpstan-ignore expr.resultUnused | ||
} | ||
|
||
public function testCannotSerialiseKey(): void | ||
{ | ||
$this->expectException(\BadMethodCallException::class); | ||
$this->expectExceptionMessage(\sprintf('Cannot serialise a %s object.', \get_class($this->key))); | ||
|
||
serialize($this->key); | ||
} | ||
|
||
public function testHidesKeyStringFromDump(): void | ||
{ | ||
$secret = new Secret(random_bytes(32)); | ||
$this->key = $this->getMockBuilder(Key::class) | ||
->setConstructorArgs([$secret]) | ||
->onlyMethods([]) | ||
->getMock() | ||
; | ||
|
||
ob_start(); | ||
var_dump($this->key); | ||
$dump = (string) ob_get_clean(); | ||
$print = print_r($this->key, true); | ||
|
||
self::assertStringNotContainsString($secret->reveal(), $dump); | ||
self::assertStringContainsString('[redacted]', $dump); | ||
self::assertStringNotContainsString($secret->reveal(), $print); | ||
self::assertStringContainsString('[redacted]', $print); | ||
} | ||
|
||
public function testGetKeyString(): void | ||
{ | ||
$secret = new Secret(random_bytes(32)); | ||
$this->key = $this->getMockBuilder(Key::class) | ||
->setConstructorArgs([$secret]) | ||
->onlyMethods([]) | ||
->getMock() | ||
; | ||
|
||
self::assertSame($secret->reveal(), $this->key->getKeyString()); | ||
} | ||
} |