getMessage()); } } /** * Decrypt the given data (arrays/objects). */ public static function decryptData($encryptedData) { try { $decrypted = Crypt::decryptString($encryptedData); return json_decode($decrypted, true); } catch (DecryptException $e) { Log::error('Error al desencriptar los datos: ' . $e->getMessage()); return null; } catch (\Exception $e) { Log::error('Error inesperado al desencriptar los datos: ' . $e->getMessage()); return null; } } /** * Encrypt a simple string (for tokens, passwords, etc.) */ public static function encryptString(string $string): string { try { return Crypt::encryptString($string); } catch (\Exception $e) { throw new \RuntimeException("Error al encriptar el string: " . $e->getMessage()); } } /** * Decrypt a simple string */ public static function decryptString(string $encryptedString): ?string { try { return Crypt::decryptString($encryptedString); } catch (DecryptException $e) { Log::error('Error al desencriptar el string: ' . $e->getMessage()); return null; } catch (\Exception $e) { Log::error('Error inesperado al desencriptar el string: ' . $e->getMessage()); return null; } } /** * Encrypt using a custom key (independent of APP_KEY) * Useful for tokens that should survive APP_KEY rotation */ public static function encryptWithCustomKey(string $string, string $key): string { try { $cipher = 'AES-256-CBC'; $ivLength = openssl_cipher_iv_length($cipher); $iv = openssl_random_pseudo_bytes($ivLength); $encrypted = openssl_encrypt($string, $cipher, $key, 0, $iv); if ($encrypted === false) { throw new \RuntimeException('Encryption failed'); } // Combinar IV + encrypted data y codificar en base64 return base64_encode($iv . $encrypted); } catch (\Exception $e) { throw new \RuntimeException("Error al encriptar con clave personalizada: " . $e->getMessage()); } } /** * Decrypt using a custom key (independent of APP_KEY) */ public static function decryptWithCustomKey(string $encryptedString, string $key): ?string { try { $cipher = 'AES-256-CBC'; $ivLength = openssl_cipher_iv_length($cipher); // Decodificar y separar IV + encrypted data $data = base64_decode($encryptedString); if ($data === false) { return null; } $iv = substr($data, 0, $ivLength); $encrypted = substr($data, $ivLength); $decrypted = openssl_decrypt($encrypted, $cipher, $key, 0, $iv); if ($decrypted === false) { Log::error('Error al desencriptar con clave personalizada'); return null; } return $decrypted; } catch (\Exception $e) { Log::error('Error inesperado al desencriptar con clave personalizada: ' . $e->getMessage()); return null; } } /** * Verify if a plain value matches a value encrypted with custom key */ public static function verifyWithCustomKey(string $plainValue, string $encryptedValue, string $key): bool { try { $decrypted = self::decryptWithCustomKey($encryptedValue, $key); return $decrypted === $plainValue; } catch (\Exception $e) { return false; } } /** * Generate a hash for searchable encrypted data */ public static function hash(string $data, string $algorithm = 'sha256'): string { return hash($algorithm, $data); } /** * Encrypt multiple fields in an array */ public static function encryptFields(array $data, array $fields): array { foreach ($fields as $field) { if (isset($data[$field])) { $data[$field] = self::encryptData($data[$field]); } } return $data; } /** * Decrypt multiple fields in an array */ public static function decryptFields(array $data, array $fields): array { foreach ($fields as $field) { if (isset($data[$field])) { $data[$field] = self::decryptData($data[$field]); } } return $data; } /** * Verify if a plain value matches an encrypted value */ public static function verifyEncrypted(string $plainValue, string $encryptedValue): bool { try { $decrypted = self::decryptString($encryptedValue); return $decrypted === $plainValue; } catch (\Exception $e) { return false; } } }