feat : add TokenEncryptor service with sodium encryption
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
21
.env
21
.env
@@ -1,24 +1,23 @@
|
|||||||
###> symfony/framework-bundle ###
|
|
||||||
APP_ENV=dev
|
APP_ENV=dev
|
||||||
APP_SECRET=
|
APP_SECRET="a64f5614357bf56aecb1d7470e431535"
|
||||||
APP_SHARE_DIR=var/share
|
APP_DEBUG=1
|
||||||
###< symfony/framework-bundle ###
|
|
||||||
|
|
||||||
###> symfony/routing ###
|
DEFAULT_URI=http://localhost/
|
||||||
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
|
|
||||||
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
|
|
||||||
DEFAULT_URI=http://localhost
|
|
||||||
###< symfony/routing ###
|
|
||||||
|
|
||||||
###> nelmio/cors-bundle ###
|
###> nelmio/cors-bundle ###
|
||||||
CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$'
|
CORS_ALLOW_ORIGIN='^https?://(localhost|127.0.0.1)(:[0-9]+)?$'
|
||||||
###< nelmio/cors-bundle ###
|
###< nelmio/cors-bundle ###
|
||||||
|
|
||||||
###> lexik/jwt-authentication-bundle ###
|
###> lexik/jwt-authentication-bundle ###
|
||||||
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
|
||||||
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
|
||||||
JWT_PASSPHRASE=
|
JWT_PASSPHRASE=c2dbeec8fa8255bdab24e88b9fc1e57927740c429ae3b930d03e51b92e13a85f
|
||||||
JWT_COOKIE_SECURE=0
|
JWT_COOKIE_SECURE=0
|
||||||
JWT_TOKEN_TTL=86400
|
JWT_TOKEN_TTL=86400
|
||||||
JWT_COOKIE_TTL=86400
|
JWT_COOKIE_TTL=86400
|
||||||
###< lexik/jwt-authentication-bundle ###
|
###< lexik/jwt-authentication-bundle ###
|
||||||
|
|
||||||
|
|
||||||
|
DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:${POSTGRES_PORT}/${POSTGRES_DB}?serverVersion=16&charset=utf8"
|
||||||
|
|
||||||
|
GITEA_ENCRYPTION_KEY=
|
||||||
52
src/Service/TokenEncryptor.php
Normal file
52
src/Service/TokenEncryptor.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use RuntimeException;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
final readonly class TokenEncryptor
|
||||||
|
{
|
||||||
|
private string $key;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire('%env(GITEA_ENCRYPTION_KEY)%')]
|
||||||
|
string $encryptionKey,
|
||||||
|
) {
|
||||||
|
if ('' === $encryptionKey) {
|
||||||
|
throw new InvalidArgumentException('GITEA_ENCRYPTION_KEY environment variable must be set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->key = sodium_hex2bin($encryptionKey);
|
||||||
|
|
||||||
|
if (SODIUM_CRYPTO_SECRETBOX_KEYBYTES !== mb_strlen($this->key, '8bit')) {
|
||||||
|
throw new InvalidArgumentException('GITEA_ENCRYPTION_KEY must be a valid sodium secret box key.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function encrypt(string $plaintext): string
|
||||||
|
{
|
||||||
|
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||||
|
$ciphertext = sodium_crypto_secretbox($plaintext, $nonce, $this->key);
|
||||||
|
|
||||||
|
return sodium_bin2hex($nonce.$ciphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function decrypt(string $encrypted): string
|
||||||
|
{
|
||||||
|
$decoded = sodium_hex2bin($encrypted);
|
||||||
|
$nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
|
||||||
|
$ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');
|
||||||
|
|
||||||
|
$plaintext = sodium_crypto_secretbox_open($ciphertext, $nonce, $this->key);
|
||||||
|
|
||||||
|
if (false === $plaintext) {
|
||||||
|
throw new RuntimeException('Failed to decrypt token.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $plaintext;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user