Files
domnitor/core/Encryption.php

107 lines
2.8 KiB
PHP
Raw Permalink Normal View History

<?php
namespace Core;
class Encryption
{
private string $key;
private string $cipher = 'AES-256-CBC';
public function __construct()
{
$key = $_ENV['APP_ENCRYPTION_KEY'] ?? null;
if (empty($key)) {
throw new \Exception('APP_ENCRYPTION_KEY is not set in .env file. Generate one using: php -r "echo base64_encode(random_bytes(32));"');
}
// Decode the base64 key
$this->key = base64_decode($key);
if (strlen($this->key) !== 32) {
throw new \Exception('APP_ENCRYPTION_KEY must be 32 bytes (base64 encoded). Generate one using: php -r "echo base64_encode(random_bytes(32));"');
}
}
/**
* Encrypt a value
*/
public function encrypt(string $value): string
{
if (empty($value)) {
return '';
}
// Generate a random IV (Initialization Vector)
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($this->cipher));
// Encrypt the value
$encrypted = openssl_encrypt($value, $this->cipher, $this->key, 0, $iv);
if ($encrypted === false) {
throw new \Exception('Encryption failed');
}
// Combine IV and encrypted data, then base64 encode
$result = base64_encode($iv . $encrypted);
return $result;
}
/**
* Decrypt a value
*/
public function decrypt(string $encrypted): string
{
if (empty($encrypted)) {
return '';
}
// Decode from base64
$data = base64_decode($encrypted);
if ($data === false) {
throw new \Exception('Invalid encrypted data');
}
// Extract IV and encrypted data
$ivLength = openssl_cipher_iv_length($this->cipher);
$iv = substr($data, 0, $ivLength);
$encryptedData = substr($data, $ivLength);
// Decrypt the value
$decrypted = openssl_decrypt($encryptedData, $this->cipher, $this->key, 0, $iv);
if ($decrypted === false) {
throw new \Exception('Decryption failed');
}
return $decrypted;
}
/**
* Generate a new encryption key (base64 encoded)
* This should be run once and the result stored in .env
*/
public static function generateKey(): string
{
return base64_encode(random_bytes(32));
}
/**
* Check if a value is encrypted (basic heuristic)
*/
public function isEncrypted(string $value): bool
{
if (empty($value)) {
return false;
}
// Encrypted values are base64 encoded
// They should be longer than typical plaintext passwords
// and contain only base64 characters
return preg_match('/^[A-Za-z0-9+\/]+=*$/', $value) && strlen($value) > 40;
}
}