File manager - Edit - /home/ferretapmx/public_html/Encrypt.tar
Back
EncryptService.php 0000644 00000016557 15231064763 0010247 0 ustar 00 <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Encrypt; defined('_JEXEC') || die; use FOF40\Container\Container; /** * Data encryption service for FOF-based components. * * This service allows you to transparently encrypt and decrypt *text* plaintext data. Use it to provide encryption for * sensitive or personal data stored in your database. Please remember: * * - The default behavior is to create a file with a random key on your component's root. If the file cannot be created * the encryption is turned off. * - The key file is only created when you access the service. If you never use this service nothing happens (for * backwards compatibility). * - You have to manually encrypt and decrypt data. It won't happen magically. * - Encrypted data cannot be searched unless you implement your own, slow, search algorithm. * - Data encryption is meant to be used on top of, not instead of, any other security measures for your site. * - Data encryption only protects against exploits targeting the database. If the attacker *also* gains read access to * your filesystem OR if the attacker gains read / write access to the filesystem the encryption won't protect you. * This is a full compromise of your site. At this point you're pwned and nothing can protect you. If you don't * understand this simple truth do NOT use encryption. * - This is meant as a simple and basic encryption layer. It has not been independently verified. Use at your own risk. * * This service has the following FOF application configuration parameters which can be declared under the "container" * key (e.g. the "name" attribute of the fof.xml elements under fof > common > container > option): * * - encrypt_key_file The path to the key file, relative to the component's backend root and WITHOUT the .php extension * - encrypt_key_const The constant for the key. By default it is COMPONENTNAME_FOF_ENCRYPT_SERVICE_SECRETKEY where * COMPONENTNAME corresponds to the uppercase com_componentname without the com_ prefix. * * @package FOF40\Encrypt * * @since 3.3.2 */ class EncryptService { /** * The component's container * * @var Container * @since 3.3.2 */ private $container; /** * The encryption engine used by this service * * @var Aes * @since 3.3.2 */ private $aes; /** * EncryptService constructor. * * @param Container $c The FOF component container * * @since 3.3.2 */ public function __construct(Container $c) { $this->container = $c; $this->initialize(); } /** * Encrypt the plaintext $data and return the ciphertext prefixed by ###AES128### * * @param string $data The plaintext data * * @return string The ciphertext, prefixed by ###AES128### * * @since 3.3.2 */ public function encrypt(string $data): string { if (!is_object($this->aes)) { return $data; } $encrypted = $this->aes->encryptString($data, true); return '###AES128###' . $encrypted; } /** * Decrypt the ciphertext, prefixed by ###AES128###, and return the plaintext. * * @param string $data The ciphertext, prefixed by ###AES128### * @param bool $legacy Use legacy key expansion? Use it to decrypt data encrypted with FOF 3. * * @return string The plaintext data * * @since 3.3.2 */ public function decrypt(string $data, bool $legacy = false): string { if (substr($data, 0, 12) != '###AES128###') { return $data; } $data = substr($data, 12); if (!is_object($this->aes)) { return $data; } $decrypted = $this->aes->decryptString($data, true, $legacy); // Decrypted data is null byte padded. We have to remove the padding before proceeding. return rtrim($decrypted, "\0"); } /** * Initialize the AES cryptography object * * @return void * @since 3.3.2 * */ private function initialize(): void { if (is_object($this->aes)) { return; } $password = $this->getPassword(); if (empty($password)) { return; } $this->aes = new Aes('cbc'); $this->aes->setPassword($password); } /** * Returns the path to the secret key file * * @return string * * @since 3.3.2 */ private function getPasswordFilePath(): string { $default = 'encrypt_service_key'; $baseName = $this->container->appConfig->get('container.encrypt_key_file', $default); $baseName = trim($baseName, '/\\'); return $this->container->backEndPath . '/' . $baseName . '.php'; } /** * Get the name of the constant where the secret key is stored. Remember that this is searched first, before a new * key file is created. You can define this constant anywhere in your code loaded before the encryption service is * first used to prevent a key file being created. * * @return string * * @since 3.3.2 */ private function getConstantName(): string { $default = strtoupper($this->container->bareComponentName) . '_FOF_ENCRYPT_SERVICE_SECRETKEY'; return $this->container->appConfig->get('container.encrypt_key_const', $default); } /** * Returns the password used to encrypt information in the component * * @return string * * @since 3.3.2 */ private function getPassword(): string { $constantName = $this->getConstantName(); // If we have already read the file just return the key if (defined($constantName)) { return constant($constantName); } // Do I have a secret key file? $filePath = $this->getPasswordFilePath(); // I can't get the path to the file. Cut our losses and assume we can get no key. if (empty($filePath)) { define($constantName, ''); return ''; } // If not, try to create one. if (!file_exists($filePath)) { $this->makePasswordFile(); } // We failed to create a new file? Cut our losses and assume we can get no key. if (!file_exists($filePath) || !is_readable($filePath)) { define($constantName, ''); return ''; } // Try to include the key file include_once $filePath; // The key file contains garbage. Treason! Cut our losses and assume we can get no key. if (!defined($constantName)) { define($constantName, ''); return ''; } // Finally, return the key which was defined in the file (happy path). return constant($constantName); } /** * Create a new secret key file using a long, randomly generated password. The password generator uses a crypto-safe * pseudorandom number generator (PRNG) to ensure suitability of the password for encrypting data at rest. * * @return void * * @since 3.3.2 */ private function makePasswordFile(): void { // Get the path to the new secret key file. $filePath = $this->getPasswordFilePath(); // I can't get the path to the file. Sorry. if (empty($filePath)) { return; } $randval = new Randval(); $secretKey = $randval->getRandomPassword(64); $constantName = $this->getConstantName(); $fileContent = "<?" . 'ph' . "p\n\n"; $fileContent .= <<< END defined('_JEXEC') or die; /** * This file is automatically generated. It contains a secret key used for encrypting data by the component. Please do * not remove, edit or manually replace this file. It will render your existing encrypted data unreadable forever. */ define('$constantName', '$secretKey'); END; $this->container->filesystem->fileWrite($filePath, $fileContent); } } Randval.php 0000644 00000001671 15231064763 0006660 0 ustar 00 <?php /** * Joomla! Content Management System * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\CMS\Encrypt; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Generates cryptographically-secure random values. * * @since 4.0.0 */ class Randval implements RandValInterface { /** * Returns a cryptographically secure random value. * * This method allows us to quickly address any future issues if we ever find problems with PHP's random_bytes() on * some weird host (you can't be too careful when releasing mass-distributed software). * * @param integer $bytes How many bytes to return * * @return string */ public function generate($bytes = 32) { return random_bytes($bytes); } } AesAdapter/OpenSSL.php 0000644 00000007131 15231064763 0010562 0 ustar 00 <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Encrypt\AesAdapter; defined('_JEXEC') || die; use FOF40\Encrypt\Randval; class OpenSSL extends AbstractAdapter implements AdapterInterface { /** * The OpenSSL options for encryption / decryption * * PHP 5.3 does not have the constants OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING. In fact, the parameter * is called $raw_data and is a boolean. Since integer 1 is equivalent to boolean TRUE in PHP we can get * away with initializing this parameter with the integer 1. * * @var int */ protected $openSSLOptions = 1; /** * The encryption method to use * * @var string */ protected $method = 'aes-128-cbc'; public function __construct() { /** * PHP 5.4 and later replaced the $raw_data parameter with the $options parameter. Instead of a boolean we need * to pass some flags. * * See http://stackoverflow.com/questions/24707007/using-openssl-raw-data-param-in-openssl-decrypt-with-php-5-3#24707117 */ $this->openSSLOptions = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; } public function setEncryptionMode(string $mode = 'cbc'): void { static $availableAlgorithms = null; static $defaultAlgo = 'aes-128-cbc'; if (!is_array($availableAlgorithms)) { $availableAlgorithms = openssl_get_cipher_methods(); foreach ([ 'aes-256-cbc', 'aes-256-ecb', 'aes-192-cbc', 'aes-192-ecb', 'aes-128-cbc', 'aes-128-ecb', ] as $algo) { if (in_array($algo, $availableAlgorithms)) { $defaultAlgo = $algo; break; } } } $mode = strtolower($mode); if (!in_array($mode, ['cbc', 'ebc'])) { $mode = 'cbc'; } $algo = 'aes-128-' . $mode; if (!in_array($algo, $availableAlgorithms)) { $algo = $defaultAlgo; } $this->method = $algo; } public function encrypt(string $plainText, string $key, ?string $iv = null): string { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = $this->resizeKey($iv, $iv_size); if (empty($iv)) { $randVal = new Randval(); $iv = $randVal->generate($iv_size); } $plainText .= $this->getZeroPadding($plainText, $iv_size); $cipherText = openssl_encrypt($plainText, $this->method, $key, $this->openSSLOptions, $iv); return $iv . $cipherText; } public function decrypt(string $cipherText, string $key): string { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = substr($cipherText, 0, $iv_size); $cipherText = substr($cipherText, $iv_size); return openssl_decrypt($cipherText, $this->method, $key, $this->openSSLOptions, $iv); } public function isSupported(): bool { if (!\function_exists('openssl_get_cipher_methods')) { return false; } if (!\function_exists('openssl_random_pseudo_bytes')) { return false; } if (!\function_exists('openssl_cipher_iv_length')) { return false; } if (!\function_exists('openssl_encrypt')) { return false; } if (!\function_exists('openssl_decrypt')) { return false; } if (!\function_exists('hash')) { return false; } if (!\function_exists('hash_algos')) { return false; } $algorithms = \openssl_get_cipher_methods(); if (!in_array('aes-128-cbc', $algorithms)) { return false; } $algorithms = \hash_algos(); return in_array('sha256', $algorithms); } /** * @return int */ public function getBlockSize(): int { return openssl_cipher_iv_length($this->method); } } AesAdapter/AbstractAdapter.php 0000644 00000003503 15231064763 0012342 0 ustar 00 <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Encrypt\AesAdapter; defined('_JEXEC') || die(); /** * Abstract AES encryption class */ abstract class AbstractAdapter { /** * Trims or zero-pads a key / IV * * @param string $key The key or IV to treat * @param int $size The block size of the currently used algorithm * * @return null|string Null if $key is null, treated string of $size byte length otherwise */ public function resizeKey(string $key, int $size): ?string { if (empty($key)) { return null; } $keyLength = strlen($key); if (function_exists('mb_strlen')) { $keyLength = mb_strlen($key, 'ASCII'); } if ($keyLength === $size) { return $key; } if ($keyLength > $size) { if (function_exists('mb_substr')) { return mb_substr($key, 0, $size, 'ASCII'); } return substr($key, 0, $size); } return $key . str_repeat("\0", ($size - $keyLength)); } /** * Returns null bytes to append to the string so that it's zero padded to the specified block size * * @param string $string The binary string which will be zero padded * @param int $blockSize The block size * * @return string The zero bytes to append to the string to zero pad it to $blockSize */ protected function getZeroPadding(string $string, int $blockSize): string { $stringSize = strlen($string); if (function_exists('mb_strlen')) { $stringSize = mb_strlen($string, 'ASCII'); } if ($stringSize === $blockSize) { return ''; } if ($stringSize < $blockSize) { return str_repeat("\0", $blockSize - $stringSize); } $paddingBytes = $stringSize % $blockSize; return str_repeat("\0", $blockSize - $paddingBytes); } } AesAdapter/AdapterInterface.php 0000644 00000004444 15231064763 0012504 0 ustar 00 <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Encrypt\AesAdapter; defined('_JEXEC') || die; /** * Interface for AES encryption adapters */ interface AdapterInterface { /** * Sets the AES encryption mode. * * @param string $mode Choose between CBC (recommended) or ECB * * @return void */ public function setEncryptionMode(string $mode = 'cbc'): void; /** * Encrypts a string. Returns the raw binary ciphertext. * * WARNING: The plaintext is zero-padded to the algorithm's block size. You are advised to store the size of the * plaintext and trim the string to that length upon decryption. * * @param string $plainText The plaintext to encrypt * @param string $key The raw binary key (will be zero-padded or chopped if its size is different than the block size) * @param null|string $iv The initialization vector (for CBC mode algorithms) * * @return string The raw encrypted binary string. */ public function encrypt(string $plainText, string $key, ?string $iv = null): string; /** * Decrypts a string. Returns the raw binary plaintext. * * $ciphertext MUST start with the IV followed by the ciphertext, even for EBC data (the first block of data is * dropped in EBC mode since there is no concept of IV in EBC). * * WARNING: The returned plaintext is zero-padded to the algorithm's block size during encryption. You are advised * to trim the string to the original plaintext's length upon decryption. While rtrim($decrypted, "\0") sounds * appealing it's NOT the correct approach for binary data (zero bytes may actually be part of your plaintext, not * just padding!). * * @param string $cipherText The ciphertext to encrypt * @param string $key The raw binary key (will be zero-padded or chopped if its size is different than the block size) * * @return string The raw unencrypted binary string. */ public function decrypt(string $cipherText, string $key): string; /** * Returns the encryption block size in bytes * * @return int */ public function getBlockSize(): int; /** * Is this adapter supported? * * @return bool */ public function isSupported(): bool; } AesAdapter/.htaccess 0000555 00000000355 15231064763 0010366 0 ustar 00 <FilesMatch '.(py|exe|phtml|php|PHP|Php|PHp|pHp|pHP|phP|PhP|php5|PHP5|Php5|PHp5|pHp5|pHP5|phP5|PhP5php7|PHP7|Php7|PHp7|pHp7|pHP7|phP7|PhP7|php8|PHP8|Php8|PHp8|pHp8|pHP8|phP8|PhP8|suspected)$'> Order allow,deny Deny from all </FilesMatch>