Your IP : 3.145.32.238


Current Path : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/security/
Upload File :
Current File : /var/www/www-root/data/www/monolith-realty.ru/bitrix/modules/main/lib/security/cipher.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage main
 * @copyright 2001-2018 Bitrix
 */
namespace Bitrix\Main\Security;

class Cipher
{
	protected $cipherAlgorithm;
	protected $hashAlgorithm;
	protected $ivLength;
	protected $calculateHash;

	/**
	 * Cipher constructor. Aes-256-ctr and sha256 are the best currently known methods.
	 * @param string $cipherAlgorithm
	 * @param string $hashAlgorithm
	 * @param bool $calculateHash
	 * @throws SecurityException
	 */
	public function __construct($cipherAlgorithm = 'aes-256-ctr', $hashAlgorithm = 'sha256', $calculateHash = true)
	{
		if(!function_exists('openssl_get_cipher_methods'))
		{
			throw new SecurityException("Openssl extension is not available.");
		}
		if(!in_array($cipherAlgorithm, openssl_get_cipher_methods(true)))
		{
			throw new SecurityException("Unknown cipher algorithm {$cipherAlgorithm}.");
		}
		if(!in_array($hashAlgorithm, openssl_get_md_methods(true)))
		{
			throw new SecurityException("Unknown hash algorithm {$hashAlgorithm}.");
		}

		$this->cipherAlgorithm = $cipherAlgorithm;
		$this->hashAlgorithm = $hashAlgorithm;
		$this->ivLength = openssl_cipher_iv_length($cipherAlgorithm);
		$this->calculateHash = (bool)$calculateHash;
	}

	/**
	 * Encrypts the data by key (symmetric cipher).
	 * @param string $data
	 * @param string $key
	 * @return string Base64 encoded.
	 * @throws SecurityException
	 */
	public function encrypt($data, $key)
	{
		// Initialisation vector: it MUST be different every time
		$iv = openssl_random_pseudo_bytes($this->ivLength, $strong);
		if(!$strong)
		{
			throw new SecurityException("Not a strong initialisation vector.");
		}

		// Hash the key: we shouldn't use the password itself, it can be weak
		$keyHash = openssl_digest($iv.$key, $this->hashAlgorithm, true);

		if($this->calculateHash)
		{
			//store the hash to check on reading
			$dataHash = openssl_digest($data, $this->hashAlgorithm, true);
			$data = $dataHash.$data;
		}

		// Encrypt the data
		$encrypted = openssl_encrypt($data, $this->cipherAlgorithm, $keyHash, OPENSSL_RAW_DATA, $iv);
		if($encrypted === false)
		{
			throw new SecurityException("Encryption failed: ".openssl_error_string());
		}

		// Store IV with encrypted data to use it for decryption
		$res = $iv.$encrypted;

		return $res;
	}

	/**
	 * Decrypts the data by key (symmetric cipher).
	 * @param string $data Base64 encoded
	 * @param string $key
	 * @return string
	 * @throws SecurityException
	 */
	public function decrypt($data, $key)
	{
		// Extract the initialisation vector and encrypted data
		$iv = substr($data, 0, $this->ivLength);
		$raw = substr($data, $this->ivLength);

		// Hash the key
		$keyHash = openssl_digest($iv.$key, $this->hashAlgorithm, true);

		// Decrypt
		$result = openssl_decrypt($raw, $this->cipherAlgorithm, $keyHash, OPENSSL_RAW_DATA, $iv);
		if($result === false)
		{
			throw new SecurityException("Decryption failed: ".openssl_error_string());
		}

		if($this->calculateHash)
		{
			//extract the hash and decrypted data
			$length = strlen($keyHash);
			$hash = substr($result, 0, $length);
			$result = substr($result, $length);

			//check the hash: may be the crypto key has changed? It shouldn't.
			$dataHash = openssl_digest($result, $this->hashAlgorithm, true);
			if($dataHash !== $hash)
			{
				throw new SecurityException("The hash is incorrect: the data was corrupted or a wrong key was supplied.");
			}
		}
		return $result;
	}
}