Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/fof30.zip
Назад
PK �%"]��<�t2 t2 Inflector/Inflector.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Inflector; defined('_JEXEC') || die; /** * An Inflector to pluralize and singularize English nouns. */ class Inflector { /** * Rules for pluralizing and singularizing of nouns. * * @var array */ protected $rules = [ // Pluralization rules. The regex on the left transforms to the regex on the right. 'pluralization' => [ '/move$/i' => 'moves', '/sex$/i' => 'sexes', '/child$/i' => 'children', '/children$/i' => 'children', '/man$/i' => 'men', '/men$/i' => 'men', '/foot$/i' => 'feet', '/feet$/i' => 'feet', '/person$/i' => 'people', '/people$/i' => 'people', '/taxon$/i' => 'taxa', '/taxa$/i' => 'taxa', '/(quiz)$/i' => '$1zes', '/^(ox)$/i' => '$1en', '/oxen$/i' => 'oxen', '/(m|l)ouse$/i' => '$1ice', '/(m|l)ice$/i' => '$1ice', '/(matr|vert|ind|suff)ix|ex$/i' => '$1ices', '/(x|ch|ss|sh)$/i' => '$1es', '/([^aeiouy]|qu)y$/i' => '$1ies', '/(?:([^f])fe|([lr])f)$/i' => '$1$2ves', '/sis$/i' => 'ses', '/([ti]|addend)um$/i' => '$1a', '/([ti]|addend)a$/i' => '$1a', '/(alumn|formul)a$/i' => '$1ae', '/(alumn|formul)ae$/i' => '$1ae', '/(buffal|tomat|her)o$/i' => '$1oes', '/(bu)s$/i' => '$1ses', '/(campu)s$/i' => '$1ses', '/(alias|status)$/i' => '$1es', '/(octop|vir)us$/i' => '$1i', '/(octop|vir)i$/i' => '$1i', '/(gen)us$/i' => '$1era', '/(gen)era$/i' => '$1era', '/(ax|test)is$/i' => '$1es', '/s$/i' => 's', '/$/' => 's', ], // Singularization rules. The regex on the left transforms to the regex on the right. 'singularization' => [ '/cookies$/i' => 'cookie', '/moves$/i' => 'move', '/sexes$/i' => 'sex', '/children$/i' => 'child', '/men$/i' => 'man', '/feet$/i' => 'foot', '/people$/i' => 'person', '/taxa$/i' => 'taxon', '/databases$/i' => 'database', '/menus$/i' => 'menu', '/(quiz)zes$/i' => '\1', '/(matr|suff)ices$/i' => '\1ix', '/(vert|ind|cod)ices$/i' => '\1ex', '/^(ox)en/i' => '\1', '/(alias|status)es$/i' => '\1', '/(tomato|hero|buffalo)es$/i' => '\1', '/([octop|vir])i$/i' => '\1us', '/(gen)era$/i' => '\1us', '/(cris|^ax|test)es$/i' => '\1is', '/is$/i' => 'is', '/us$/i' => 'us', '/ias$/i' => 'ias', '/(shoe)s$/i' => '\1', '/(o)es$/i' => '\1e', '/(bus)es$/i' => '\1', '/(campus)es$/i' => '\1', '/([m|l])ice$/i' => '\1ouse', '/(x|ch|ss|sh)es$/i' => '\1', '/(m)ovies$/i' => '\1ovie', '/(s)eries$/i' => '\1eries', '/(v)ies$/i' => '\1ie', '/([^aeiouy]|qu)ies$/i' => '\1y', '/([lr])ves$/i' => '\1f', '/(tive)s$/i' => '\1', '/(hive)s$/i' => '\1', '/([^f])ves$/i' => '\1fe', '/(^analy)ses$/i' => '\1sis', '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', '/([ti]|addend)a$/i' => '\1um', '/(alumn|formul)ae$/i' => '$1a', '/(n)ews$/i' => '\1ews', '/(.*)ss$/i' => '\1ss', '/(.*)s$/i' => '\1', ], // Uncountable objects are always singular 'uncountable' => [ 'aircraft', 'cannon', 'deer', 'equipment', 'fish', 'information', 'money', 'moose', 'news', 'rice', 'series', 'sheep', 'species', 'swine', ], ]; /** * Cache of pluralized and singularized nouns. * * @var array */ protected $cache = [ 'singularized' => [], 'pluralized' => [], ]; public function deleteCache() { $this->cache['pluralized'] = []; $this->cache['singularized'] = []; } /** * Add a word to the cache, useful to make exceptions or to add words in other languages. * * @param string $singular word. * @param string $plural word. * * @return void */ public function addWord($singular, $plural) { $this->cache['pluralized'][$singular] = $plural; $this->cache['singularized'][$plural] = $singular; } /** * Singular English word to plural. * * @param string $word word to pluralize. * * @return string Plural noun. */ public function pluralize($word) { // Get the cached noun of it exists if (isset($this->cache['pluralized'][$word])) { return $this->cache['pluralized'][$word]; } // Check if the noun is already in plural form, i.e. in the singularized cache if (isset($this->cache['singularized'][$word])) { return $word; } // Create the plural noun if (in_array($word, $this->rules['uncountable'])) { $_cache['pluralized'][$word] = $word; return $word; } foreach ($this->rules['pluralization'] as $regexp => $replacement) { $matches = null; $plural = preg_replace($regexp, $replacement, $word, -1, $matches); if ($matches > 0) { $_cache['pluralized'][$word] = $plural; return $plural; } } return $word; } /** * Plural English word to singular. * * @param string $word Word to singularize. * * @return string Singular noun. */ public function singularize($word) { // Get the cached noun of it exists if (isset($this->cache['singularized'][$word])) { return $this->cache['singularized'][$word]; } // Check if the noun is already in singular form, i.e. in the pluralized cache if (isset($this->cache['pluralized'][$word])) { return $word; } // Create the singular noun if (in_array($word, $this->rules['uncountable'])) { $_cache['singularized'][$word] = $word; return $word; } foreach ($this->rules['singularization'] as $regexp => $replacement) { $matches = null; $singular = preg_replace($regexp, $replacement, $word, -1, $matches); if ($matches > 0) { $_cache['singularized'][$word] = $singular; return $singular; } } return $word; } /** * Returns given word as CamelCased. * * Converts a word like "foo_bar" or "foo bar" to "FooBar". It * will remove non alphanumeric characters from the word, so * "who's online" will be converted to "WhoSOnline" * * @param string $word Word to convert to camel case. * * @return string UpperCamelCasedWord */ public function camelize($word) { $word = preg_replace('/[^a-zA-Z0-9\s]/', ' ', $word); $word = str_replace(' ', '', ucwords(strtolower(str_replace('_', ' ', $word)))); return $word; } /** * Converts a word "into_it_s_underscored_version" * * Convert any "CamelCased" or "ordinary Word" into an "underscored_word". * * @param string $word Word to underscore * * @return string Underscored word */ public function underscore($word) { $word = preg_replace('/(\s)+/', '_', $word); $word = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $word)); return $word; } /** * Convert any "CamelCased" word into an array of strings * * Returns an array of strings each of which is a substring of string formed * by splitting it at the camelcased letters. * * @param string $word Word to explode * * @return array Array of strings */ public function explode($word) { $result = explode('_', self::underscore($word)); return $result; } /** * Convert an array of strings into a "CamelCased" word. * * @param array $words Array to implode * * @return string UpperCamelCasedWord */ public function implode($words) { $result = self::camelize(implode('_', $words)); return $result; } /** * Returns a human-readable string from $word. * * Returns a human-readable string from $word, by replacing * underscores with a space, and by upper-casing the initial * character by default. * * @param string $word String to "humanize" * * @return string Human-readable word */ public function humanize($word) { $result = ucwords(strtolower(str_replace("_", " ", $word))); return $result; } /** * Returns camelBacked version of a string. Same as camelize but first char is lowercased. * * @param string $string String to be camelBacked. * * @return string * * @see camelize */ public function variablize($string) { $string = self::camelize(self::underscore($string)); $result = strtolower(substr($string, 0, 1)); $variable = preg_replace('/\\w/', $result, $string, 1); return $variable; } /** * Check to see if an English word is singular * * @param string $string The word to check * * @return boolean */ public function isSingular($string) { // Check cache assuming the string is plural. $singular = $this->cache['singularized'][$string] ?? null; $plural = $singular && isset($this->cache['pluralized'][$singular]) ? $this->cache['pluralized'][$singular] : null; if ($singular && $plural) { return $plural != $string; } // If string is not in the cache, try to pluralize and singularize it. return self::singularize(self::pluralize($string)) == $string; } /** * Check to see if an English word is plural. * * @param string $string String to be checked. * * @return boolean */ public function isPlural($string) { // Uncountable objects are always singular (e.g. information) if (in_array($string, $this->rules['uncountable'])) { return false; } // Check cache assuming the string is singular. $plural = $this->cache['pluralized'][$string] ?? null; $singular = $plural && isset($this->cache['singularized'][$plural]) ? $this->cache['singularized'][$plural] : null; if ($plural && $singular) { return $singular != $string; } // If string is not in the cache, try to singularize and pluralize it. return self::pluralize(self::singularize($string)) == $string; } /** * Gets a part of a CamelCased word by index. * * Use a negative index to start at the last part of the word (-1 is the * last part) * * @param string $string Word * @param integer $index Index of the part * @param string $default Default value * * @return string */ public function getPart($string, $index, $default = null) { $parts = self::explode($string); if ($index < 0) { $index = count($parts) + $index; } return $parts[$index] ?? $default; } } PK �%"]�.��� � Encrypt/EncryptService.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; use FOF30\Container\Container; use FOF30\Utils\Phpfunc; /** * 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 FOF30\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($data) { 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### * * @return string The plaintext data * * @since 3.3.2 */ public function decrypt($data) { 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); // 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() { if (is_object($this->aes)) { return; } $password = $this->getPassword(); if (empty($password)) { return; } $phpFunc = new Phpfunc(); $this->aes = new Aes($password, 128, 'cbc', $phpFunc); } /** * Returns the path to the secret key file * * @return string * * @since 3.3.2 */ private function getPasswordFilePath() { $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() { $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 * * @return string * * @since 3.3.2 */ private function getPassword() { $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() { // 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; } $phpFunc = new Phpfunc(); $randval = new Randval($phpFunc); $secretKey = $randval->getRandomPassword(64); $constantName = $this->getConstantName(); $fileContent = "<?" . 'ph' . "p\n\n"; $fileContent .= <<< END /** * 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); } } PK �%"]���� � Encrypt/Randval.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; use FOF30\Utils\Phpfunc; /** * Generates cryptographically-secure random values. */ class Randval implements RandvalInterface { /** * @var Phpfunc */ protected $phpfunc; /** * * Constructor. * * @param Phpfunc $phpfunc An object to intercept PHP function calls; * this makes testing easier. * */ public function __construct(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof Phpfunc)) { $phpfunc = new Phpfunc(); } $this->phpfunc = $phpfunc; } /** * * Returns a cryptographically secure random value. * * @param integer $bytes How many bytes to return * * @return string */ public function generate($bytes = 32) { if ($this->phpfunc->extension_loaded('openssl') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN)) { $strong = false; $randBytes = openssl_random_pseudo_bytes($bytes, $strong); if ($strong) { return $randBytes; } } return $this->genRandomBytes($bytes); } /** * Generate random bytes. Adapted from Joomla! 3.2. * * @param integer $length Length of the random data to generate * * @return string Random binary data */ public function genRandomBytes($length = 32) { $length = (int) $length; $sslStr = ''; /* * Collect any entropy available in the system along with a number * of time measurements of operating system randomness. */ $bitsPerRound = 2; $maxTimeMicro = 400; $shaHashLength = 20; $randomStr = ''; $total = $length; // Check if we can use /dev/urandom. $urandom = false; $handle = null; // This is PHP 5.3.3 and up if ($this->phpfunc->function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom')) { $handle = @fopen('/dev/urandom', 'rb'); if ($handle) { $urandom = true; } } while ($length > strlen($randomStr)) { $bytes = ($total > $shaHashLength) ? $shaHashLength : $total; $total -= $bytes; /* * Collect any entropy available from the PHP system and filesystem. * If we have ssl data that isn't strong, we use it once. */ $entropy = random_int(0, mt_getrandmax()) . uniqid(random_int(0, mt_getrandmax()), true) . $sslStr; $entropy .= implode('', @fstat(fopen(__FILE__, 'r'))); $entropy .= memory_get_usage(); $sslStr = ''; if ($urandom) { stream_set_read_buffer($handle, 0); $entropy .= @fread($handle, $bytes); } else { /* * There is no external source of entropy so we repeat calls * to mt_rand until we are assured there's real randomness in * the result. * * Measure the time that the operations will take on average. */ $samples = 3; $duration = 0; for ($pass = 0; $pass < $samples; ++$pass) { $microStart = microtime(true) * 1000000; $hash = sha1(random_int(0, mt_getrandmax()), true); for ($count = 0; $count < 50; ++$count) { $hash = sha1($hash, true); } $microEnd = microtime(true) * 1000000; $entropy .= $microStart . $microEnd; if ($microStart >= $microEnd) { $microEnd += 1000000; } $duration += $microEnd - $microStart; } $duration = $duration / $samples; /* * Based on the average time, determine the total rounds so that * the total running time is bounded to a reasonable number. */ $rounds = (int) (($maxTimeMicro / $duration) * 50); /* * Take additional measurements. On average we can expect * at least $bitsPerRound bits of entropy from each measurement. */ $iter = $bytes * (int) ceil(8 / $bitsPerRound); for ($pass = 0; $pass < $iter; ++$pass) { $microStart = microtime(true); $hash = sha1(random_int(0, mt_getrandmax()), true); for ($count = 0; $count < $rounds; ++$count) { $hash = sha1($hash, true); } $entropy .= $microStart . microtime(true); } } $randomStr .= sha1($entropy, true); } if ($urandom) { @fclose($handle); } return substr($randomStr, 0, $length); } /** * Return a randomly generated password using safe characters (a-z, A-Z, 0-9). * * @param int $length How many characters long should the password be. Default is 64. * * @return string * * @since 3.3.2 */ public function getRandomPassword($length = 64) { $salt = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $base = strlen($salt); $makepass = ''; /* * Start with a cryptographic strength random string, then convert it to * a string with the numeric base of the salt. * Shift the base conversion on each character so the character * distribution is even, and randomize the start shift so it's not * predictable. */ $random = $this->generate($length + 1); $shift = ord($random[0]); for ($i = 1; $i <= $length; ++$i) { $makepass .= $salt[($shift + ord($random[$i])) % $base]; $shift += ord($random[$i]); } return $makepass; } } PK �%"]g�Xy y Encrypt/RandvalInterface.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; interface RandvalInterface { /** * * Returns a cryptographically secure random value. * * @return string * */ public function generate(); } PK �%"]w��* * Encrypt/Totp.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; class Totp { /** * @var int The length of the resulting passcode (default: 6 digits) */ private $passCodeLength = 6; /** * @var number The PIN modulo. It is set automatically to log10(passCodeLength) */ private $pinModulo; /** * The length of the secret key, in characters (default: 10) * * @var int */ private $secretLength = 10; /** * The time step between successive TOTPs in seconds (default: 30 seconds) * * @var int */ private $timeStep = 30; /** * The Base32 encoder class * * @var Base32|null */ private $base32 = null; /** * Initialises an RFC6238-compatible TOTP generator. Please note that this * class does not implement the constraint in the last paragraph of §5.2 * of RFC6238. It's up to you to ensure that the same user/device does not * retry validation within the same Time Step. * * @param int $timeStep The Time Step (in seconds). Use 30 to be compatible with Google Authenticator. * @param int $passCodeLength The generated passcode length. Default: 6 digits. * @param int $secretLength The length of the secret key. Default: 10 bytes (80 bits). * @param Base32 $base32 The base32 en/decrypter */ public function __construct($timeStep = 30, $passCodeLength = 6, $secretLength = 10, Base32 $base32 = null) { $this->timeStep = $timeStep; $this->passCodeLength = $passCodeLength; $this->secretLength = $secretLength; $this->pinModulo = 10 ** $this->passCodeLength; if (is_null($base32)) { $this->base32 = new Base32(); } else { $this->base32 = $base32; } } /** * Get the time period based on the $time timestamp and the Time Step * defined. If $time is skipped or set to null the current timestamp will * be used. * * @param int|null $time Timestamp * * @return int The time period since the UNIX Epoch */ public function getPeriod($time = null) { if (is_null($time)) { $time = time(); } $period = floor($time / $this->timeStep); return $period; } /** * Check is the given passcode $code is a valid TOTP generated using secret * key $secret * * @param string $secret The Base32-encoded secret key * @param string $code The passcode to check * @param int $time The time to check it against. Leave null to check for the current server time. * * @return boolean True if the code is valid */ public function checkCode($secret, $code, $time = null) { $time = $this->getPeriod($time); for ($i = -1; $i <= 1; $i++) { if ($this->getCode($secret, ($time + $i) * $this->timeStep) == $code) { return true; } } return false; } /** * Gets the TOTP passcode for a given secret key $secret and a given UNIX * timestamp $time * * @param string $secret The Base32-encoded secret key * @param int $time UNIX timestamp * * @return string */ public function getCode($secret, $time = null) { $period = $this->getPeriod($time); $secret = $this->base32->decode($secret); $time = pack("N", $period); $time = str_pad($time, 8, chr(0), STR_PAD_LEFT); $hash = hash_hmac('sha1', $time, $secret, true); $offset = ord(substr($hash, -1)); $offset = $offset & 0xF; $truncatedHash = $this->hashToInt($hash, $offset) & 0x7FFFFFFF; $pinValue = str_pad($truncatedHash % $this->pinModulo, $this->passCodeLength, "0", STR_PAD_LEFT); return $pinValue; } /** * Returns a QR code URL for easy setup of TOTP apps like Google Authenticator * * @param string $user User * @param string $hostname Hostname * @param string $secret Secret string * * @return string */ public function getUrl($user, $hostname, $secret) { $url = sprintf("otpauth://totp/%s@%s?secret=%s", $user, $hostname, $secret); $encoder = "https://chart.googleapis.com/chart?chs=200x200&chld=Q|2&cht=qr&chl="; $encoderURL = $encoder . urlencode($url); return $encoderURL; } /** * Generates a (semi-)random Secret Key for TOTP generation * * @return string */ public function generateSecret() { $secret = ""; for ($i = 1; $i <= $this->secretLength; $i++) { $c = random_int(0, 255); $secret .= pack("c", $c); } return $this->base32->encode($secret); } /** * Extracts a part of a hash as an integer * * @param string $bytes The hash * @param string $start The char to start from (0 = first char) * * @return string */ protected function hashToInt($bytes, $start) { $input = substr($bytes, $start, strlen($bytes) - $start); $val2 = unpack("N", substr($input, 0, 4)); return $val2[1]; } } PK �%"]�W� Encrypt/Base32.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; use InvalidArgumentException; /** * Base32 encoding class, used by the TOTP */ class Base32 { /** * CSRFC3548 * * The character set as defined by RFC3548 * @link http://www.ietf.org/rfc/rfc3548.txt */ public const CSRFC3548 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; /** * Convert any string to a base32 string * This should be binary safe... * * @param string $str The string to convert * * @return string The converted base32 string */ public function encode($str) { return $this->fromBin($this->str2bin($str)); } /** * Convert any base32 string to a normal sctring * This should be binary safe... * * @param string $str The base32 string to convert * * @return string The normal string */ public function decode($str) { $str = strtoupper($str); return $this->bin2str($this->tobin($str)); } /** * Converts any ascii string to a binary string * * @param string $str The string you want to convert * * @return string String of 0's and 1's */ private function str2bin($str) { $chrs = unpack('C*', $str); return vsprintf(str_repeat('%08b', count($chrs)), $chrs); } /** * Converts a binary string to an ascii string * * @param string $str The string of 0's and 1's you want to convert * * @return string The ascii output * * @throws InvalidArgumentException */ private function bin2str($str) { if (strlen($str) % 8 > 0) { throw new InvalidArgumentException('Length must be divisible by 8'); } if (!preg_match('/^[01]+$/', $str)) { throw new InvalidArgumentException('Only 0\'s and 1\'s are permitted'); } preg_match_all('/.{8}/', $str, $chrs); $chrs = array_map('bindec', $chrs[0]); // I'm just being slack here array_unshift($chrs, 'C*'); return call_user_func_array('pack', $chrs); } /** * Converts a correct binary string to base32 * * @param string $str The string of 0's and 1's you want to convert * * @return string String encoded as base32 * * @throws InvalidArgumentException */ private function fromBin($str) { if (strlen($str) % 8 > 0) { throw new InvalidArgumentException('Length must be divisible by 8'); } if (!preg_match('/^[01]+$/', $str)) { throw new InvalidArgumentException('Only 0\'s and 1\'s are permitted'); } // Base32 works on the first 5 bits of a byte, so we insert blanks to pad it out $str = preg_replace('/(.{5})/', '000$1', $str); // We need a string divisible by 5 $length = strlen($str); $rbits = $length & 7; if ($rbits > 0) { // Excessive bits need to be padded $ebits = substr($str, $length - $rbits); $str = substr($str, 0, $length - $rbits); $str .= "000$ebits" . str_repeat('0', 5 - strlen($ebits)); } preg_match_all('/.{8}/', $str, $chrs); $chrs = array_map([$this, 'mapCharset'], $chrs[0]); return implode('', $chrs); } /** * Accepts a base32 string and returns an ascii binary string * * @param string $str The base32 string to convert * * @return string Ascii binary string * * @throws InvalidArgumentException */ private function toBin($str) { if (!preg_match('/^[' . self::CSRFC3548 . ']+$/', $str)) { throw new InvalidArgumentException('Base64 string must match character set'); } // Convert the base32 string back to a binary string $str = implode('', array_map([$this, 'mapBin'], str_split($str))); // Remove the extra 0's we added $str = preg_replace('/000(.{5})/', '$1', $str); // Remove padding if necessary $length = strlen($str); $rbits = $length & 7; if ($rbits > 0) { $str = substr($str, 0, $length - $rbits); } return $str; } /** * Used with array_map to map the bits from a binary string * directly into a base32 character set * * @param string $str The string of 0's and 1's you want to convert * * @return string Resulting base32 character * * @access private */ private function mapCharset($str) { // Huh! $x = self::CSRFC3548; return $x[bindec($str)]; } /** * Used with array_map to map the characters from a base32 * character set directly into a binary string * * @param string $chr The character to map * * @return string String of 0's and 1's * * @access private */ private function mapBin($chr) { return sprintf('%08b', strpos(self::CSRFC3548, $chr)); } } PK �%"]�#0�� � Encrypt/Aes.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 2, or later */ namespace FOF30\Encrypt; defined('_JEXEC') || die; use FOF30\Encrypt\AesAdapter\AdapterInterface; use FOF30\Encrypt\AesAdapter\OpenSSL; use FOF30\Utils\Phpfunc; /** * A simple abstraction to AES encryption * * Usage: * * // Create a new instance. The key is ignored – only use it if you have legacy encrypted content you need to decrypt * $aes = new Aes('ignored'); * // Set the password. Do not use uf you have legacy encrypted content you need to decrypt * $aes->setPassword('yourRealPassword'); * // Encrypt something. * $cipherText = $aes->encryptString($sourcePlainText); * // Decrypt something * $plainText = $aes->decryptString($sourceCipherText); */ class Aes { /** * The cipher key. * * @var string */ private $key = ''; /** * The AES encryption adapter in use. * * @var AdapterInterface */ private $adapter; /** * Initialise the AES encryption object. * * Note: If the key is not 16 bytes this class will do a stupid key expansion for legacy reasons (produce the * SHA-256 of the key string and throw away half of it). * * @param string $key The encryption key (password). It can be a raw key (16 bytes) or a passphrase. * @param int $strength Bit strength (128, 192 or 256) – ALWAYS USE 128 BITS. THIS PARAMETER IS DEPRECATED. * @param string $mode Encryption mode. Can be ebc or cbc. We recommend using cbc. * @param Phpfunc $phpfunc For testing */ public function __construct($key, $strength = 128, $mode = 'cbc', Phpfunc $phpfunc = null) { $this->adapter = new OpenSSL(); if (!$this->adapter->isSupported($phpfunc)) { throw new \RuntimeException('Your server does not have the PHP OpenSSL extension enabled. This is required for encryption handling.'); } $this->adapter->setEncryptionMode($mode, $strength); $this->setPassword($key, true); } /** * Is AES encryption supported by this PHP installation? * * @return boolean */ public static function isSupported(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof $phpfunc)) { $phpfunc = new Phpfunc(); } $adapter = new OpenSSL(); if (!$adapter->isSupported($phpfunc)) { return false; } if (!$phpfunc->function_exists('base64_encode')) { return false; } if (!$phpfunc->function_exists('base64_decode')) { return false; } if (!$phpfunc->function_exists('hash_algos')) { return false; } $algorightms = $phpfunc->hash_algos(); if (!in_array('sha256', $algorightms)) { return false; } return true; } /** * Sets the password for this instance. * * WARNING: Do not use the legacy mode, it's insecure * * @param string $password The password (either user-provided password or binary encryption key) to use * @param bool $legacyMode True to use the legacy key expansion. We recommend against using it. */ public function setPassword($password, $legacyMode = false) { $this->key = $password; $passLength = strlen($password); if (function_exists('mb_strlen')) { $passLength = mb_strlen($password, 'ASCII'); } // Legacy mode was doing something stupid, requiring a key of 32 bytes. DO NOT USE LEGACY MODE! if ($legacyMode && ($passLength != 32)) { // Legacy mode: use the sha256 of the password $this->key = hash('sha256', $password, true); // We have to trim or zero pad the password (we end up throwing half of it away in Rijndael-128 / AES...) $this->key = $this->adapter->resizeKey($this->key, $this->adapter->getBlockSize()); } } /** * Encrypts a string using AES * * @param string $stringToEncrypt The plaintext to encrypt * @param bool $base64encoded Should I Base64-encode the result? * * @return string The cryptotext. Please note that the first 16 bytes of * the raw string is the IV (initialisation vector) which * is necessary for decoding the string. */ public function encryptString($stringToEncrypt, $base64encoded = true) { $blockSize = $this->adapter->getBlockSize(); $randVal = new Randval(); $iv = $randVal->generate($blockSize); $key = $this->getExpandedKey($blockSize, $iv); $cipherText = $this->adapter->encrypt($stringToEncrypt, $key, $iv); // Optionally pass the result through Base64 encoding if ($base64encoded) { $cipherText = base64_encode($cipherText); } // Return the result return $cipherText; } /** * Decrypts a ciphertext into a plaintext string using AES * * @param string $stringToDecrypt The ciphertext to decrypt. The first 16 bytes of the raw string must contain * the IV (initialisation vector). * @param bool $base64encoded Should I Base64-decode the data before decryption? * * @return string The plain text string */ public function decryptString($stringToDecrypt, $base64encoded = true) { if ($base64encoded) { $stringToDecrypt = base64_decode($stringToDecrypt); } // Extract IV $iv_size = $this->adapter->getBlockSize(); $iv = substr($stringToDecrypt, 0, $iv_size); $key = $this->getExpandedKey($iv_size, $iv); // Decrypt the data $plainText = $this->adapter->decrypt($stringToDecrypt, $key); return $plainText; } /** * @param $blockSize * @param $iv * * @return string */ public function getExpandedKey($blockSize, $iv) { $key = $this->key; $passLength = strlen($key); if (function_exists('mb_strlen')) { $passLength = mb_strlen($key, 'ASCII'); } if ($passLength != $blockSize) { $iterations = 1000; $salt = $this->adapter->resizeKey($iv, 16); $key = hash_pbkdf2('sha256', $this->key, $salt, $iterations, $blockSize, true); } return $key; } } if (!function_exists('hash_pbkdf2')) { function hash_pbkdf2($algo, $password, $salt, $count, $length = 0, $raw_output = false) { if (!in_array(strtolower($algo), hash_algos())) { trigger_error(__FUNCTION__ . '(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING); } if (!is_numeric($count)) { trigger_error(__FUNCTION__ . '(): expects parameter 4 to be long, ' . gettype($count) . ' given', E_USER_WARNING); } if (!is_numeric($length)) { trigger_error(__FUNCTION__ . '(): expects parameter 5 to be long, ' . gettype($length) . ' given', E_USER_WARNING); } if ($count <= 0) { trigger_error(__FUNCTION__ . '(): Iterations must be a positive integer: ' . $count, E_USER_WARNING); } if ($length < 0) { trigger_error(__FUNCTION__ . '(): Length must be greater than or equal to 0: ' . $length, E_USER_WARNING); } $output = ''; $block_count = $length ? ceil($length / strlen(hash($algo, '', $raw_output))) : 1; for ($i = 1; $i <= $block_count; $i++) { $last = $xorsum = hash_hmac($algo, $salt . pack('N', $i), $password, true); for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algo, $last, $password, true)); } $output .= $xorsum; } if (!$raw_output) { $output = bin2hex($output); } return $length ? substr($output, 0, $length) : $output; } } PK �%"]�v�� '