$attributes */ public function get($model, string $key, $value, array $attributes) { if ($value === null || $value === '') { return $value; } try { return Crypt::decryptString($value); } catch (\Throwable $e) { // Not an encrypted payload (or bad key) — return as-is. return $value; } } /** * Prepare the given value for storage. * * @param mixed $model * @param string $key * @param mixed $value * @param array $attributes * @return mixed */ public function set($model, string $key, $value, array $attributes) { if ($value === null || $value === '') { return $value; } $stringValue = (string) $value; // Ziel: Immer Klartext in der DB speichern. // Wenn ein verschlüsselter Laravel-Payload übergeben wurde, entschlüsseln und im Klartext ablegen. if (self::looksEncrypted($stringValue)) { try { return Crypt::decryptString($stringValue); } catch (\Throwable $e) { // Falls Entschlüsselung (noch) nicht möglich: als Fallback unverändert ablegen, // aber bevorzugt sollte der Aufrufer bereits Klartext liefern. return $stringValue; } } // Bereits Klartext → so speichern return $stringValue; } private static function looksEncrypted(string $value): bool { // Laravel's Crypt::encryptString returns base64-encoded JSON string // with keys like iv/value/mac and sometimes tag. $decoded = base64_decode($value, true); if ($decoded === false) { return false; } $json = json_decode($decoded, true); if (!is_array($json)) { return false; } $hasCoreKeys = isset($json['iv'], $json['value'], $json['mac']); // 'tag' may or may not exist depending on cipher/version return $hasCoreKeys; } }