115 lines
3.4 KiB
PHP
115 lines
3.4 KiB
PHP
<?php
|
|
/**
|
|
* Encryption/Decryption for sensitive data like API keys.
|
|
*
|
|
* ENTERPRISE SECURITY NOTICE:
|
|
* This class manages encryption of API credentials using AES-256-CBC.
|
|
* The encryption key is stored in wp_options as 'wpfmj_encryption_key'.
|
|
*
|
|
* CRITICAL FOR PRODUCTION:
|
|
* - The encryption key MUST be backed up with your database
|
|
* - If the key is lost/changed, ALL saved automations will fail
|
|
* - During site migrations, ensure wp_options table includes this key
|
|
* - For multi-environment setups, consider using wp-config.php constants
|
|
* - Monitor error logs for decryption failures
|
|
*
|
|
* @package WPFMJ
|
|
* @subpackage WPFMJ/includes
|
|
*/
|
|
|
|
class WPFMJ_Encryption {
|
|
|
|
/**
|
|
* Get encryption method (configurable via filter).
|
|
*
|
|
* @return string Encryption method
|
|
*/
|
|
private static function get_method() {
|
|
$method = apply_filters('wpfmj_encryption_method', 'AES-256-CBC');
|
|
|
|
// Validate that the method is available
|
|
$available_methods = openssl_get_cipher_methods();
|
|
if (!in_array($method, $available_methods, true)) {
|
|
error_log("WPFMJ: Invalid encryption method '{$method}', falling back to AES-256-CBC");
|
|
$method = 'AES-256-CBC';
|
|
}
|
|
|
|
return $method;
|
|
}
|
|
|
|
/**
|
|
* Get the encryption key.
|
|
*/
|
|
private static function get_key() {
|
|
$key = get_option('wpfmj_encryption_key');
|
|
|
|
if (!$key) {
|
|
// Generate a new key if it doesn't exist
|
|
$key = base64_encode(random_bytes(32));
|
|
add_option('wpfmj_encryption_key', $key, '', false);
|
|
}
|
|
|
|
return base64_decode($key);
|
|
}
|
|
|
|
/**
|
|
* Encrypt data.
|
|
*/
|
|
public static function encrypt($data) {
|
|
if (empty($data)) {
|
|
return '';
|
|
}
|
|
|
|
$key = self::get_key();
|
|
$method = self::get_method();
|
|
$iv_length = openssl_cipher_iv_length($method);
|
|
$iv = openssl_random_pseudo_bytes($iv_length);
|
|
|
|
$encrypted = openssl_encrypt($data, $method, $key, 0, $iv);
|
|
|
|
// Combine IV and encrypted data
|
|
return base64_encode($iv . $encrypted);
|
|
}
|
|
|
|
/**
|
|
* Decrypt data.
|
|
*/
|
|
public static function decrypt($data) {
|
|
if (empty($data)) {
|
|
return '';
|
|
}
|
|
|
|
try {
|
|
$key = self::get_key();
|
|
$method = self::get_method();
|
|
$decoded_data = base64_decode($data);
|
|
|
|
if ($decoded_data === false) {
|
|
error_log('WPFMJ Decryption Error: Invalid base64 data');
|
|
return false;
|
|
}
|
|
|
|
$iv_length = openssl_cipher_iv_length($method);
|
|
|
|
if (strlen($decoded_data) <= $iv_length) {
|
|
error_log('WPFMJ Decryption Error: Data too short');
|
|
return false;
|
|
}
|
|
|
|
$iv = substr($decoded_data, 0, $iv_length);
|
|
$encrypted = substr($decoded_data, $iv_length);
|
|
|
|
$decrypted = openssl_decrypt($encrypted, $method, $key, 0, $iv);
|
|
|
|
if ($decrypted === false) {
|
|
error_log('WPFMJ Decryption Error: Decryption failed - possibly corrupted data or wrong key');
|
|
return false;
|
|
}
|
|
|
|
return $decrypted;
|
|
} catch (Exception $e) {
|
|
error_log('WPFMJ Decryption Error: ' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
}
|