commit basic
This commit is contained in:
68
src/App/Crypto.php
Executable file
68
src/App/Crypto.php
Executable file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App;
|
||||
|
||||
final class Crypto
|
||||
{
|
||||
private string $key;
|
||||
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
if (!extension_loaded('sodium')) {
|
||||
throw new \RuntimeException('libsodium extension not available');
|
||||
}
|
||||
|
||||
$raw = getenv('DATA_KEY') ?: '';
|
||||
$raw = trim($raw);
|
||||
if ($raw === '') {
|
||||
throw new \RuntimeException('DATA_KEY env not set');
|
||||
}
|
||||
|
||||
// base64?
|
||||
if (str_starts_with($raw, 'base64:')) {
|
||||
$raw = substr($raw, 7);
|
||||
}
|
||||
$decoded = base64_decode($raw, true);
|
||||
if ($decoded !== false && strlen($decoded) >= SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
|
||||
$raw = $decoded;
|
||||
} elseif (ctype_xdigit($raw) && strlen($raw) >= SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES * 2) {
|
||||
$raw = hex2bin($raw);
|
||||
}
|
||||
|
||||
if (strlen($raw) < SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
|
||||
throw new \RuntimeException('DATA_KEY invalid length');
|
||||
}
|
||||
|
||||
$this->key = substr($raw, 0, SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES);
|
||||
}
|
||||
|
||||
public function encrypt(string $plaintext): string
|
||||
{
|
||||
if ($plaintext === '') {
|
||||
return '';
|
||||
}
|
||||
$nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
|
||||
$cipher = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($plaintext, '', $nonce, $this->key);
|
||||
return base64_encode($nonce . $cipher);
|
||||
}
|
||||
|
||||
public function decrypt(?string $blob): string
|
||||
{
|
||||
if ($blob === null || $blob === '') {
|
||||
return '';
|
||||
}
|
||||
$raw = base64_decode($blob, true);
|
||||
if ($raw === false || strlen($raw) <= SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) {
|
||||
return '';
|
||||
}
|
||||
$nonce = substr($raw, 0, SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
|
||||
$cipher = substr($raw, SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);
|
||||
try {
|
||||
$plain = sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($cipher, '', $nonce, $this->key);
|
||||
return $plain === false ? '' : $plain;
|
||||
} catch (\Throwable) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user