tigerstyle-life9/includes/class-encryption.php
Ryan Malloy e92b7f8700 Initial commit: TigerStyle Life9 v1.0.0
Because cats have 9 lives, but servers don't - so they need
backup-restore! Complete backup solution with S3/MinIO support.

- Full WordPress backup (files + database)
- S3 / MinIO / S3-compatible storage backends
- Scheduled automatic backups
- Disaster recovery / one-click restore
- Backup integrity validation
- Cat-themed admin interface

Includes build.sh and .distignore for WordPress-installable release ZIPs.
2026-05-27 14:32:00 -06:00

268 lines
8.2 KiB
PHP

<?php
/**
* TigerStyle Life9 Encryption Class
*
* Military-grade encryption for backup files
*
* @package TigerStyleLife9
* @subpackage Security
* @since 1.0.0
*/
// Exit if accessed directly
if (!defined('ABSPATH')) {
exit;
}
/**
* TigerStyle Life9 Encryption Manager
*
* Handles encryption/decryption with cat-themed security
*
* @since 1.0.0
*/
class TigerStyle_Life9_Encryption {
/**
* Encryption method
*/
const ENCRYPTION_METHOD = 'aes-256-gcm';
/**
* Key derivation iterations
*/
const PBKDF2_ITERATIONS = 100000;
/**
* Generate encryption key from password
*
* @param string $password Password
* @param string $salt Salt
* @return string Derived key
*/
public static function derive_key($password, $salt) {
return hash_pbkdf2('sha256', $password, $salt, self::PBKDF2_ITERATIONS, 32, true);
}
/**
* Generate random salt
*
* @param int $length Salt length
* @return string Random salt
*/
public static function generate_salt($length = 32) {
return random_bytes($length);
}
/**
* Generate random IV
*
* @return string Random IV
*/
public static function generate_iv() {
return random_bytes(openssl_cipher_iv_length(self::ENCRYPTION_METHOD));
}
/**
* Encrypt data
*
* @param string $data Data to encrypt
* @param string $password Password
* @return array Encrypted data with metadata
*/
public static function encrypt($data, $password) {
// Generate salt and IV
$salt = self::generate_salt();
$iv = self::generate_iv();
// Derive key
$key = self::derive_key($password, $salt);
// Encrypt data
$tag = '';
$encrypted = openssl_encrypt($data, self::ENCRYPTION_METHOD, $key, OPENSSL_RAW_DATA, $iv, $tag);
if ($encrypted === false) {
throw new Exception(__('🙀 Encryption failed! The cat\'s secret powers are temporarily unavailable.', 'tigerstyle-life9'));
}
return [
'data' => $encrypted,
'salt' => $salt,
'iv' => $iv,
'tag' => $tag,
'method' => self::ENCRYPTION_METHOD
];
}
/**
* Decrypt data
*
* @param array $encrypted_data Encrypted data with metadata
* @param string $password Password
* @return string Decrypted data
*/
public static function decrypt($encrypted_data, $password) {
// Extract components
$data = $encrypted_data['data'];
$salt = $encrypted_data['salt'];
$iv = $encrypted_data['iv'];
$tag = $encrypted_data['tag'];
$method = $encrypted_data['method'];
// Derive key
$key = self::derive_key($password, $salt);
// Decrypt data
$decrypted = openssl_decrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv, $tag);
if ($decrypted === false) {
throw new Exception(__('🙀 Decryption failed! Wrong password or corrupted data. The cat is suspicious.', 'tigerstyle-life9'));
}
return $decrypted;
}
/**
* Encrypt file
*
* @param string $source_file Source file path
* @param string $destination_file Destination file path
* @param string $password Password
* @return bool Success
*/
public static function encrypt_file($source_file, $destination_file, $password) {
if (!file_exists($source_file)) {
throw new Exception(__('🙀 Source file not found! The cat cannot encrypt what doesn\'t exist.', 'tigerstyle-life9'));
}
// Read file content
$data = file_get_contents($source_file);
if ($data === false) {
throw new Exception(__('🙀 Cannot read source file! The cat\'s access is denied.', 'tigerstyle-life9'));
}
// Encrypt data
$encrypted = self::encrypt($data, $password);
// Create encrypted file header
$header = [
'version' => '1.0',
'method' => $encrypted['method'],
'salt' => base64_encode($encrypted['salt']),
'iv' => base64_encode($encrypted['iv']),
'tag' => base64_encode($encrypted['tag']),
'timestamp' => time(),
'original_size' => strlen($data)
];
// Write encrypted file
$file_content = "TIGERSTYLE_LIFE9_ENCRYPTED\n";
$file_content .= json_encode($header) . "\n";
$file_content .= "DATA_START\n";
$file_content .= base64_encode($encrypted['data']);
$result = file_put_contents($destination_file, $file_content);
if ($result === false) {
throw new Exception(__('🙀 Cannot write encrypted file! The cat\'s write access is denied.', 'tigerstyle-life9'));
}
return true;
}
/**
* Decrypt file
*
* @param string $source_file Source encrypted file path
* @param string $destination_file Destination file path
* @param string $password Password
* @return bool Success
*/
public static function decrypt_file($source_file, $destination_file, $password) {
if (!file_exists($source_file)) {
throw new Exception(__('🙀 Encrypted file not found! The cat cannot decrypt what doesn\'t exist.', 'tigerstyle-life9'));
}
// Read encrypted file
$content = file_get_contents($source_file);
if ($content === false) {
throw new Exception(__('🙀 Cannot read encrypted file! The cat\'s access is denied.', 'tigerstyle-life9'));
}
// Parse file content
$lines = explode("\n", $content);
if ($lines[0] !== 'TIGERSTYLE_LIFE9_ENCRYPTED') {
throw new Exception(__('🙀 Invalid encrypted file format! This is not a cat-encrypted file.', 'tigerstyle-life9'));
}
$header = json_decode($lines[1], true);
if (!$header) {
throw new Exception(__('🙀 Corrupted file header! The cat cannot parse the encryption metadata.', 'tigerstyle-life9'));
}
if ($lines[2] !== 'DATA_START') {
throw new Exception(__('🙀 Invalid file structure! The cat is confused by this format.', 'tigerstyle-life9'));
}
$encrypted_data = base64_decode($lines[3]);
// Prepare decryption data
$decryption_data = [
'data' => $encrypted_data,
'salt' => base64_decode($header['salt']),
'iv' => base64_decode($header['iv']),
'tag' => base64_decode($header['tag']),
'method' => $header['method']
];
// Decrypt data
$decrypted = self::decrypt($decryption_data, $password);
// Write decrypted file
$result = file_put_contents($destination_file, $decrypted);
if ($result === false) {
throw new Exception(__('🙀 Cannot write decrypted file! The cat\'s write access is denied.', 'tigerstyle-life9'));
}
return true;
}
/**
* Generate secure password
*
* @param int $length Password length
* @return string Generated password
*/
public static function generate_password($length = 32) {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $characters[random_int(0, strlen($characters) - 1)];
}
return $password;
}
/**
* Hash password for storage
*
* @param string $password Password to hash
* @return string Hashed password
*/
public static function hash_password($password) {
return password_hash($password, PASSWORD_ARGON2ID);
}
/**
* Verify password against hash
*
* @param string $password Password to verify
* @param string $hash Hash to verify against
* @return bool Verification result
*/
public static function verify_password($password, $hash) {
return password_verify($password, $hash);
}
}