Files
desktop/src/App/RegistrationSecretBox.php
Lars Gebhardt-Kusche 344dbb9b79
All checks were successful
Deploy / deploy-staging (push) Successful in 58s
Deploy / deploy-production (push) Has been skipped
ldaü
2026-06-15 01:03:55 +02:00

74 lines
1.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App;
use RuntimeException;
final class RegistrationSecretBox
{
private const CIPHER = 'aes-256-gcm';
public function __construct(
private readonly string $keyMaterial,
) {
}
public function isConfigured(): bool
{
return trim($this->keyMaterial) !== '';
}
public function encrypt(string $plaintext): string
{
$key = $this->normalizedKey();
$iv = random_bytes(12);
$tag = '';
$ciphertext = openssl_encrypt($plaintext, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv, $tag);
if ($ciphertext === false) {
throw new RuntimeException('Das Passwort konnte nicht verschlüsselt werden.');
}
return base64_encode($iv . $tag . $ciphertext);
}
public function decrypt(string $encoded): string
{
$raw = base64_decode($encoded, true);
if ($raw === false || strlen($raw) < 28) {
throw new RuntimeException('Das gespeicherte Passwort ist beschädigt.');
}
$key = $this->normalizedKey();
$iv = substr($raw, 0, 12);
$tag = substr($raw, 12, 16);
$ciphertext = substr($raw, 28);
$plaintext = openssl_decrypt($ciphertext, self::CIPHER, $key, OPENSSL_RAW_DATA, $iv, $tag);
if ($plaintext === false) {
throw new RuntimeException('Das gespeicherte Passwort konnte nicht entschlüsselt werden.');
}
return $plaintext;
}
private function normalizedKey(): string
{
if (!$this->isConfigured()) {
throw new RuntimeException('REGISTRATION_PASSWORD_KEY ist nicht gesetzt.');
}
$trimmed = trim($this->keyMaterial);
$decoded = base64_decode($trimmed, true);
if ($decoded !== false && strlen($decoded) >= 32) {
return substr($decoded, 0, 32);
}
return hash('sha256', $trimmed, true);
}
}