Skip to content

Commit 1af6a0d

Browse files
Encryptors tests
Signed-off-by: Dusan Malusev <[email protected]>
1 parent b8d0c69 commit 1af6a0d

File tree

10 files changed

+190
-49
lines changed

10 files changed

+190
-49
lines changed

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
"require": {
2727
"php": ">=8.1",
2828
"ext-sodium": "*",
29-
"illuminate/support": "^8|^9|^10",
30-
"illuminate/contracts": "^8|^9|^10",
29+
"illuminate/collections": "^8|^9|^10",
3130
"illuminate/config": "^8|^9|^10",
32-
"illuminate/hashing": "^8|^9|^10",
31+
"illuminate/contracts": "^8|^9|^10",
3332
"illuminate/encryption": "^8|^9|^10",
34-
"illuminate/collections": "^8|^9|^10"
33+
"illuminate/hashing": "^8|^9|^10",
34+
"illuminate/support": "^8|^9|^10"
3535
},
3636
"require-dev": {
3737
"nunomaduro/collision": "^7.10",
@@ -96,4 +96,4 @@
9696
"@php vendor/bin/phpunit"
9797
]
9898
}
99-
}
99+
}

composer.lock

Lines changed: 25 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Encryption/AesGcm256Encryptor.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace BrosSquad\LaravelCrypto\Encryption;
66

77
use BrosSquad\LaravelCrypto\Encoder\Encoder;
8+
use BrosSquad\LaravelCrypto\Encoder\JsonEncoder;
89
use BrosSquad\LaravelCrypto\Keys\Loader;
910
use Exception;
1011
use Illuminate\Contracts\Encryption\DecryptException;
@@ -21,8 +22,8 @@ final class AesGcm256Encryptor implements Encrypter, KeyGeneration, StringEncryp
2122

2223
public function __construct(
2324
private readonly Loader $keyLoader,
24-
private readonly LoggerInterface $logger,
25-
private readonly Encoder $encoder,
25+
private readonly Encoder $encoder = new JsonEncoder(),
26+
private readonly ?LoggerInterface $logger = null,
2627
) {
2728
}
2829

@@ -38,7 +39,7 @@ public function encrypt($value, $serialize = true): string
3839
$encrypted = sodium_crypto_aead_aes256gcm_encrypt($serialized, $nonce, $nonce, $this->getKey());
3940
return Base64::constantUrlEncodeNoPadding($nonce . $encrypted);
4041
} catch (Exception $e) {
41-
$this->logger->error($e->getMessage(), [
42+
$this->logger?->error($e->getMessage(), [
4243
'exception' => $e,
4344
'stack' => $e->getTraceAsString(),
4445
]);
@@ -55,7 +56,7 @@ public function decrypt($payload, $unserialize = true)
5556
try {
5657
$decrypted = sodium_crypto_aead_aes256gcm_decrypt($cipherText, $nonce, $nonce, $this->keyLoader->getKey());
5758
} catch (Exception $e) {
58-
$this->logger->error($e->getMessage(), [
59+
$this->logger?->error($e->getMessage(), [
5960
'stack' => $e->getTraceAsString(),
6061
'exception' => $e,
6162
]);

src/Encryption/XChaCha20Poly1305Encryptor.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace BrosSquad\LaravelCrypto\Encryption;
66

77
use BrosSquad\LaravelCrypto\Encoder\Encoder;
8+
use BrosSquad\LaravelCrypto\Encoder\JsonEncoder;
89
use BrosSquad\LaravelCrypto\Keys\Loader;
910
use BrosSquad\LaravelCrypto\Support\Base64;
1011
use Exception;
@@ -18,8 +19,8 @@ final class XChaCha20Poly1305Encryptor
1819

1920
public function __construct(
2021
private readonly Loader $keyLoader,
21-
private readonly LoggerInterface $logger,
22-
private readonly Encoder $encoder,
22+
private readonly Encoder $encoder = new JsonEncoder(),
23+
private readonly ?LoggerInterface $logger = null,
2324
) {
2425
}
2526

@@ -39,12 +40,12 @@ public function encrypt($value, $serialize = true): string
3940
);
4041
return Base64::constantUrlEncodeNoPadding($nonce . $encrypted);
4142
} catch (Exception $e) {
42-
$this->logger->error($e->getMessage(), [
43+
$this->logger?->error($e->getMessage(), [
4344
'exception' => $e,
4445
'value' => $value,
4546
'serialize' => $serialize,
4647
]);
47-
throw new EncryptException('Value cannot be encrypted');
48+
throw new EncryptException('Value cannot be encrypted ' . $e->getMessage());
4849
}
4950
}
5051

@@ -62,10 +63,9 @@ public function decrypt($payload, $unserialize = true)
6263
$this->keyLoader->getKey()
6364
);
6465
} catch (Exception $e) {
65-
$this->logger->error($e->getMessage(), [
66+
$this->logger?->error($e->getMessage(), [
6667
'exception' => $e,
67-
'value' => $value,
68-
'serialize' => $serialize,
68+
'serialize' => $unserialize,
6969
]);
7070
throw new DecryptException('Payload cannot be decrypted');
7171
}
@@ -77,7 +77,7 @@ public function decrypt($payload, $unserialize = true)
7777
return $decrypted;
7878
}
7979

80-
public static function generateKey(string $cipher): string
80+
public static function generateKey(string $_): string
8181
{
8282
return sodium_crypto_aead_xchacha20poly1305_ietf_keygen();
8383
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use BrosSquad\LaravelCrypto\Encryption\AesGcm256Encryptor;
6+
7+
it('should encrypt/decrypt data', function (bool $serialize) {
8+
$encryptor = new AesGcm256Encryptor(inMemoryKeyLoader());
9+
$data = $serialize ? ['data'] : 'hello world';
10+
$encrypted = $encryptor->encrypt($data, $serialize);
11+
12+
expect($encrypted)
13+
->toBeString()
14+
->and($encryptor->decrypt($encrypted, $serialize))
15+
->toBe($data);
16+
})->with([true, false]);
17+
18+
it('should encrypt/decrypt string', function () {
19+
$encryptor = new AesGcm256Encryptor(inMemoryKeyLoader());
20+
$data = 'hello world';
21+
$encrypted = $encryptor->encryptString($data);
22+
23+
expect($encrypted)
24+
->toBeString()
25+
->and($encryptor->decryptString($encrypted))
26+
->toBe($data);
27+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use BrosSquad\LaravelCrypto\Encryption\XChaCha20Poly1305Encryptor;
6+
7+
it('should encrypt/decrypt data', function (bool $serialize) {
8+
$encryptor = new XChaCha20Poly1305Encryptor(inMemoryKeyLoader());
9+
$data = $serialize ? ['data'] : 'hello world';
10+
$encrypted = $encryptor->encrypt($data, $serialize);
11+
12+
expect($encrypted)
13+
->toBeString()
14+
->and($encryptor->decrypt($encrypted, $serialize))
15+
->toBe($data);
16+
})->with([true, false]);
17+
18+
it('should encrypt/decrypt string', function () {
19+
$encryptor = new XChaCha20Poly1305Encryptor(inMemoryKeyLoader());
20+
$data = 'hello world';
21+
$encrypted = $encryptor->encryptString($data);
22+
23+
expect($encrypted)
24+
->toBeString()
25+
->and($encryptor->decryptString($encrypted))
26+
->toBe($data);
27+
});

tests/InMemoryAppKeyLoader.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BrosSquad\LaravelCrypto\Tests;
6+
7+
use BrosSquad\LaravelCrypto\Keys\Loader;
8+
use Illuminate\Support\Str;
9+
10+
class InMemoryAppKeyLoader implements Loader
11+
{
12+
public function __construct(private readonly string $key)
13+
{
14+
}
15+
16+
public function getKey(): string|array
17+
{
18+
return Str::of($this->key)
19+
->remove('base64:', $this->key)
20+
->fromBase64()
21+
->toString();
22+
}
23+
}

tests/Pest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,44 @@
22

33
declare(strict_types=1);
44

5+
use BrosSquad\LaravelCrypto\Tests\InMemoryAppKeyLoader;
56
use BrosSquad\LaravelCrypto\Tests\TestCase;
7+
use BrosSquad\LaravelCrypto\Keys\Loader;
68

79
uses(TestCase::class)->in(__DIR__);
10+
11+
function inMemoryKeyLoader(): Loader
12+
{
13+
return new InMemoryAppKeyLoader(config('app.key'));
14+
}
15+
16+
expect()->extend('toBeBase64', function () {
17+
if (!preg_match('/^[-A-Za-z0-9+\/]+={0,3}$/', preg_quote($this->value, '/'))) {
18+
throw new RuntimeException(sprintf('Value %s is not a valid base64 string', $this->value));
19+
}
20+
21+
return $this;
22+
});
23+
24+
expect()->extend('toBeBase64NoPadding', function () {
25+
if (!preg_match('/^[-A-Za-z0-9+\/]+$/', preg_quote($this->value, '/'))) {
26+
throw new RuntimeException(sprintf('Value %s is not a valid base64 string', $this->value));
27+
}
28+
return $this;
29+
});
30+
31+
expect()->extend('toBeBase64Url', function () {
32+
if (!preg_match('/^[-A-Za-z0-9_-]+={0,3}$/', $this->value)) {
33+
throw new RuntimeException(sprintf('Value %s is not a valid base64 string', $this->value));
34+
}
35+
36+
return $this;
37+
});
38+
39+
expect()->extend('toBeBase64UrlNoPadding', function () {
40+
if (!preg_match('/^[-A-Za-z0-9_-]+$/', $this->value)) {
41+
throw new RuntimeException(sprintf('Value %s is not a valid base64 string', $this->value));
42+
}
43+
44+
return $this;
45+
});

0 commit comments

Comments
 (0)