Your IP : 216.73.216.229


Current Path : /home/jeromecohp/www/plugins/system/yooessentials/modules/core/src/Encryption/
Upload File :
Current File : /home/jeromecohp/www/plugins/system/yooessentials/modules/core/src/Encryption/Encrypter.php

<?php
/**
 * @package   Essentials YOOtheme Pro (Freemium) 2.0.19 build 1026.0920
 * @author    ZOOlanders https://www.zoolanders.com
 * @copyright Copyright (C) Joolanders, SL
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace ZOOlanders\YOOessentials\Encryption;

use ZOOlanders\YOOessentials\Encrypter as EncrypterInterface;

class Encrypter implements EncrypterInterface
{
    /**
     * @var Library
     */
    protected $library;

    /**
     * @var string
     */
    protected $cipherKey;

    /**
     * @var string
     */
    protected $hashKey;

    /**
     * @var string
     */
    protected $hashAlgo = 'sha256';

    /**
     * Constructor.
     *
     * @param string $password
     * @param string $salt
     *
     * @throws \RuntimeException
     */
    public function __construct(string $password, string $salt = '')
    {
        if (is_callable('openssl_encrypt')) {
            $this->library = new OpenSSLLibrary();
        } elseif (is_callable('mcrypt_encrypt')) {
            $this->library = new McryptLibrary();
        } else {
            throw new \RuntimeException('Encryption not supported. Install OpenSSL or Mcrypt.');
        }

        [$this->cipherKey, $this->hashKey] = static::generateKeys($this->hashAlgo, $password, $salt);
    }

    /**
     * @inheritdoc
     */
    public function encrypt($data, $serialize = true): string
    {
        $iv = $this->library->generateIv();
        $data = $this->library->encrypt($serialize ? serialize($data) : $data, $this->cipherKey, $iv);
        $hash = hash_hmac($this->hashAlgo, $iv . $data, $this->hashKey);
        $encoded = array_map('base64_encode', [$iv, $data, $hash]);

        return implode('.', $encoded);
    }

    /**
     * @inheritdoc
     */
    public function decrypt($data, $serialize = true): string
    {
        $encoded = explode('.', $data);

        if (count($encoded) !== 3) {
            return false;
        }

        [$iv, $data, $hash] = array_map('base64_decode', $encoded);

        if (hash_hmac($this->hashAlgo, $iv . $data, $this->hashKey) !== $hash) {
            return false;
        }

        $data = $this->library->decrypt($data, $this->cipherKey, $iv);

        return $serialize ? unserialize($data) : $data;
    }

    /**
     * Generates a PBKDF2 key derivation of a supplied password.
     *
     * @param string $algorithm
     * @param string $password
     * @param string $salt
     * @param int    $iterations
     * @param int    $length
     * @param bool   $raw_output
     *
     * @return string
     */
    public static function pbkdf2(
        string $algorithm,
        string $password,
        string $salt,
        int $iterations,
        int $length = 0,
        bool $raw_output = false
    ): string {
        // With PHP 7.4+ Hash extension is always available
        if (!$raw_output) {
            $length = $length * 2;
        }

        return hash_pbkdf2($algorithm, $password, $salt, $iterations, $length, $raw_output);
    }

    /**
     * Generates a cipher and a hash key using PBKDF2.
     *
     * @param string $algorithm
     * @param string $password
     * @param string $salt
     *
     * @return array
     */
    protected static function generateKeys(string $algorithm, string $password, string $salt): array
    {
        $key = static::pbkdf2($algorithm, $password, $salt, strlen($password ?? '') >= 32 ? 1 : 1000, 32, true);

        return [substr($key, 0, 16), substr($key, 16)];
    }
}