183 lines
5.4 KiB
PHP
183 lines
5.4 KiB
PHP
<?php
|
|
namespace App\Helpers;
|
|
|
|
use Illuminate\Support\Facades\Crypt;
|
|
use Illuminate\Contracts\Encryption\DecryptException;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class EncryptionHelper
|
|
{
|
|
/**
|
|
* Encrypt the given data (arrays/objects).
|
|
*/
|
|
public static function encryptData($data)
|
|
{
|
|
try {
|
|
return Crypt::encryptString(json_encode($data));
|
|
} catch (\Exception $e) {
|
|
throw new \RuntimeException("Error al encriptar los datos: " . $e->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;
|
|
}
|
|
}
|
|
}
|