Klartext (Legacy-Verhalten) } // Bevorzugt libsodium (PHP-Core seit 7.2), sonst OpenSSL. if (function_exists('sodium_crypto_secretbox')) { $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES); $cipher = sodium_crypto_secretbox($plaintext, $nonce, $key); return self::PREFIX . base64_encode($nonce . $cipher); } if (function_exists('openssl_encrypt')) { $ivLen = openssl_cipher_iv_length('aes-256-gcm'); $iv = random_bytes($ivLen); $tag = ''; $cipher = openssl_encrypt($plaintext, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag); if ($cipher === false) { return $plaintext; } return self::PREFIX . base64_encode($iv . $tag . $cipher); } // Keine Krypto-Funktion verfuegbar -> Klartext (besser als Datenverlust) return $plaintext; } /** * Entschluesselt einen Wert. Nicht-verschluesselte Werte (Legacy/Klartext) * werden unveraendert zurueckgegeben. */ public static function decrypt($value) { if ($value === null || $value === '' || strpos($value, self::PREFIX) !== 0) { return $value; // Klartext-Passthrough } $key = self::key(); if ($key === null) { return $value; } $raw = base64_decode(substr($value, strlen(self::PREFIX)), true); if ($raw === false) { return $value; } if (function_exists('sodium_crypto_secretbox_open')) { $nonceLen = SODIUM_CRYPTO_SECRETBOX_NONCEBYTES; if (strlen($raw) <= $nonceLen) { return $value; } $nonce = substr($raw, 0, $nonceLen); $cipher = substr($raw, $nonceLen); $plain = sodium_crypto_secretbox_open($cipher, $nonce, $key); return $plain === false ? $value : $plain; } if (function_exists('openssl_decrypt')) { $ivLen = openssl_cipher_iv_length('aes-256-gcm'); $tagLen = 16; if (strlen($raw) <= $ivLen + $tagLen) { return $value; } $iv = substr($raw, 0, $ivLen); $tag = substr($raw, $ivLen, $tagLen); $cipher = substr($raw, $ivLen + $tagLen); $plain = openssl_decrypt($cipher, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag); return $plain === false ? $value : $plain; } return $value; } /** Prueft, ob ein Wert bereits in unserem verschluesselten Format vorliegt. */ public static function isEncrypted($value) { return is_string($value) && strpos($value, self::PREFIX) === 0; } /** Prueft, ob ein gueltiger APP_KEY konfiguriert ist (fuer Admin-Warnhinweis). */ public static function hasKey() { return self::key() !== null; } }