Skip to content

Commit 87df0df

Browse files
fix: key generator
Signed-off-by: Dusan Malusev <[email protected]>
1 parent 7bad699 commit 87df0df

11 files changed

+219
-147
lines changed

src/Console/GenerateCryptoKeysCommand.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
use CodeLieutenant\LaravelCrypto\Keys\AppKey;
88
use CodeLieutenant\LaravelCrypto\Keys\Blake2bHashingKey;
99
use CodeLieutenant\LaravelCrypto\Keys\EdDSASignerKey;
10+
use CodeLieutenant\LaravelCrypto\Keys\Generators\AppKeyGenerator;
11+
use CodeLieutenant\LaravelCrypto\Keys\Generators\Blake2bHashingKeyGenerator;
12+
use CodeLieutenant\LaravelCrypto\Keys\Generators\EdDSASignerKeyGenerator;
13+
use CodeLieutenant\LaravelCrypto\Keys\Generators\HmacKeyGenerator;
1014
use CodeLieutenant\LaravelCrypto\Keys\HmacKey;
1115
use Exception;
1216
use Illuminate\Console\Command;
@@ -29,10 +33,10 @@ class GenerateCryptoKeysCommand extends Command
2933
protected $description = 'Generate crypto keys (APP_KEY, EdDSA, BLAKE2B_HASHING_CRYPTO_KEY)';
3034

3135
public function handle(
32-
EdDSASignerKey $edDSAGenerator,
33-
AppKey $appKeyGenerator,
34-
Blake2bHashingKey $blake2bKeyGenerator,
35-
HmacKey $hmacKeyGenerator,
36+
EdDSASignerKeyGenerator $edDSAGenerator,
37+
AppKeyGenerator $appKeyGenerator,
38+
Blake2bHashingKeyGenerator $blake2bKeyGenerator,
39+
HmacKeyGenerator $hmacKeyGenerator,
3640
): int {
3741
$show = $this->option('show');
3842
$eddsa = !$this->option('no-eddsa');

src/Keys/AppKey.php

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,62 +10,25 @@
1010
use Illuminate\Contracts\Config\Repository;
1111
use Illuminate\Encryption\Encrypter;
1212

13-
class AppKey implements Loader, Generator
13+
class AppKey implements Loader
1414
{
15-
use EnvKeySaver;
1615
use LaravelKeyParser;
1716

1817
protected static string $key;
1918

20-
public const ENV = 'APP_KEY';
21-
protected const CONFIG_KEY_PATH = 'app.key';
22-
protected const CONFIG_CIPHER_PATH = 'app.cipher';
19+
public const CONFIG_KEY_PATH = 'app.key';
2320

24-
public function __construct(protected readonly Repository $config)
25-
{
26-
}
27-
28-
public static function init(Repository $config): static
21+
public static function make(Repository $config): static
2922
{
3023
if (!isset(static::$key)) {
3124
static::$key = self::parseKey($config->get(static::CONFIG_KEY_PATH));
3225
}
3326

34-
return new static($config);
27+
return new static();
3528
}
3629

37-
3830
public function getKey(): string|array
3931
{
4032
return self::$key;
4133
}
42-
43-
public function generate(?string $write): ?string
44-
{
45-
$old = $this->config->get(static::CONFIG_KEY_PATH);
46-
$cipher = $this->config->get(static::CONFIG_CIPHER_PATH);
47-
48-
$new = $this->formatKey(
49-
match (Encryption::tryFrom($cipher)) {
50-
Encryption::SodiumAES256GCM => AesGcm256Encryptor::generateKey($cipher),
51-
Encryption::SodiumXChaCha20Poly1305 => XChaCha20Poly1305Encryptor::generateKey($cipher),
52-
default => Encrypter::generateKey($cipher),
53-
}
54-
);
55-
56-
if ($write === null) {
57-
return $new;
58-
}
59-
60-
$this->config->set(static::CONFIG_KEY_PATH, $new);
61-
62-
$this->writeNewEnvironmentFileWith($write, [
63-
static::ENV => [
64-
'old' => $old,
65-
'new' => $new,
66-
],
67-
]);
68-
69-
return null;
70-
}
7134
}

src/Keys/Blake2bHashingKey.php

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,5 @@
99

1010
class Blake2bHashingKey extends AppKey
1111
{
12-
use EnvKeySaver;
13-
use LaravelKeyParser;
14-
15-
public const KEY_SIZE = 32;
16-
public const ENV = 'CRYPTO_BLAKE2B_HASHING_KEY';
17-
protected const CONFIG_KEY_PATH = 'crypto.hashing.config.blake2b.key';
18-
19-
public function generate(?string $write): ?string
20-
{
21-
$old = $this->config->get(static::CONFIG_CIPHER_PATH);
22-
$new = $this->formatKey(Random::bytes(static::KEY_SIZE));
23-
24-
$this->config->set(static::CONFIG_CIPHER_PATH, $new);
25-
26-
if ($write === null) {
27-
return $new;
28-
}
29-
30-
$this->writeNewEnvironmentFileWith($write, [
31-
static::ENV => [
32-
'old' => $old ?? '',
33-
'new' => $new,
34-
],
35-
]);
36-
37-
return null;
38-
}
39-
40-
public function getKey(): string|array
41-
{
42-
return static::$key;
43-
}
12+
public const CONFIG_KEY_PATH = 'crypto.signing.keys.hmac';
4413
}

src/Keys/EdDSASignerKey.php

Lines changed: 3 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use RuntimeException;
1111
use SplFileObject;
1212

13-
class EdDSASignerKey implements Loader, Generator
13+
class EdDSASignerKey implements Loader
1414
{
1515
public const KEY_LENGTH = SODIUM_CRYPTO_SIGN_KEYPAIRBYTES;
1616
public const PUBLIC_KEY_LENGTH = SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES;
@@ -21,13 +21,8 @@ class EdDSASignerKey implements Loader, Generator
2121
private static string $privateKey;
2222
private static string $publicKey;
2323

24-
public function __construct(
25-
private readonly Repository $config,
26-
private readonly LoggerInterface $logger,
27-
) {
28-
}
2924

30-
public static function init(Repository $config, LoggerInterface $logger): static
25+
public static function make(Repository $config, LoggerInterface $logger): static
3126
{
3227
if (!isset(static::$publicKey, static::$privateKey)) {
3328
$path = $config->get(static::CONFIG_KEY_PATH);
@@ -39,7 +34,7 @@ public static function init(Repository $config, LoggerInterface $logger): static
3934
[static::$publicKey, static::$privateKey] = static::parseKeys($path, $logger);
4035
}
4136

42-
return new static($config, $logger);
37+
return new static();
4338
}
4439

4540
protected static function parseKeys(string $keyPath, LoggerInterface $logger): array
@@ -71,55 +66,5 @@ public function getKey(): string|array
7166
return [self::$publicKey, self::$privateKey];
7267
}
7368

74-
public function generate(?string $write): ?string
75-
{
76-
$keyPair = sodium_crypto_sign_keypair();
77-
$privateKey = bin2hex(sodium_crypto_sign_secretkey($keyPair));
78-
$publicKey = bin2hex(sodium_crypto_sign_publickey($keyPair));
79-
80-
$key = implode(PHP_EOL, [$publicKey, $privateKey]);
81-
82-
if ($write === null) {
83-
return $key;
84-
}
85-
86-
$path = $this->config->get(self::CONFIG_KEY_PATH);
87-
88-
if ($path === null) {
89-
throw new RuntimeException('File for EdDSA signer is not set');
90-
}
91-
92-
if (!@file_exists($concurrentDirectory = dirname($path)) && !@mkdir(
93-
$concurrentDirectory,
94-
0740,
95-
true
96-
) && !is_dir(
97-
$concurrentDirectory
98-
)) {
99-
throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
100-
}
101-
102-
$file = new SplFileObject($path, 'wb');
10369

104-
if ($file->flock(LOCK_EX) === false) {
105-
throw new RuntimeException('Error while locking file (exclusive/writing)');
106-
}
107-
108-
try {
109-
if ($file->fwrite($key) === false) {
110-
throw new RuntimeException('Error while writing public key to file');
111-
}
112-
} finally {
113-
if ($file->flock(LOCK_UN) === false) {
114-
$this->logger->warning('Error while unlocking file');
115-
}
116-
117-
sodium_memzero($privateKey);
118-
sodium_memzero($publicKey);
119-
sodium_memzero($keyPair);
120-
sodium_memzero($key);
121-
}
122-
123-
return null;
124-
}
12570
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeLieutenant\LaravelCrypto\Keys\Generators;
6+
7+
use CodeLieutenant\LaravelCrypto\Encryption\AesGcm256Encryptor;
8+
use CodeLieutenant\LaravelCrypto\Encryption\Encryption;
9+
use CodeLieutenant\LaravelCrypto\Encryption\XChaCha20Poly1305Encryptor;
10+
use CodeLieutenant\LaravelCrypto\Keys\EnvKeySaver;
11+
use Illuminate\Contracts\Config\Repository;
12+
use Illuminate\Encryption\Encrypter;
13+
14+
class AppKeyGenerator implements Generator
15+
{
16+
use EnvKeySaver;
17+
18+
protected const CONFIG_CIPHER_PATH = 'app.cipher';
19+
protected const CONFIG_KEY_PATH = 'app.key';
20+
21+
public const ENV = 'APP_KEY';
22+
23+
public function __construct(protected readonly Repository $config)
24+
{
25+
}
26+
27+
public function generate(?string $write): ?string
28+
{
29+
$old = $this->config->get(static::CONFIG_KEY_PATH);
30+
$cipher = $this->config->get(static::CONFIG_CIPHER_PATH);
31+
32+
$new = $this->formatKey(
33+
match (Encryption::tryFrom($cipher)) {
34+
Encryption::SodiumAES256GCM => AesGcm256Encryptor::generateKey($cipher),
35+
Encryption::SodiumXChaCha20Poly1305 => XChaCha20Poly1305Encryptor::generateKey($cipher),
36+
default => Encrypter::generateKey($cipher),
37+
}
38+
);
39+
40+
if ($write === null) {
41+
return $new;
42+
}
43+
44+
$this->config->set(static::CONFIG_KEY_PATH, $new);
45+
46+
$this->writeNewEnvironmentFileWith($write, [
47+
static::ENV => [
48+
'old' => $old,
49+
'new' => $new,
50+
],
51+
]);
52+
53+
return null;
54+
}
55+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace CodeLieutenant\LaravelCrypto\Keys\Generators;
6+
7+
use CodeLieutenant\LaravelCrypto\Keys\EnvKeySaver;
8+
use CodeLieutenant\LaravelCrypto\Support\Random;
9+
use Illuminate\Contracts\Config\Repository;
10+
11+
class Blake2bHashingKeyGenerator implements Generator
12+
{
13+
use EnvKeySaver;
14+
15+
public const KEY_SIZE = 32;
16+
17+
public const ENV = 'CRYPTO_BLAKE2B_HASHING_KEY';
18+
public const CONFIG_KEY_PATH = 'crypto.hashing.config.blake2b.key';
19+
20+
public function __construct(protected readonly Repository $config)
21+
{
22+
}
23+
24+
public function generate(?string $write): ?string
25+
{
26+
$old = $this->config->get(static::CONFIG_KEY_PATH);
27+
$new = $this->formatKey(Random::bytes(static::KEY_SIZE));
28+
29+
$this->config->set(static::CONFIG_KEY_PATH, $new);
30+
31+
if ($write === null) {
32+
return $new;
33+
}
34+
35+
$this->writeNewEnvironmentFileWith($write, [
36+
static::ENV => [
37+
'old' => $old ?? '',
38+
'new' => $new,
39+
],
40+
]);
41+
42+
return null;
43+
}
44+
}

0 commit comments

Comments
 (0)