<?php namespace HashOver;// Copyright (C) 2010-2021 Jacob Barkdull// This file is part of HashOver.//// HashOver is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as// published by the Free Software Foundation, either version 3 of the// License, or (at your option) any later version.//// HashOver is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with HashOver.  If not, see <http://www.gnu.org/licenses/>.// Encryption methodsclass Crypto extends Secrets{	protected $prefix;	protected $cost = '$10$';	protected $encryptionHash;	protected $ivSize;	protected $cipher = 'aes-128-cbc';	protected $options;	protected $alphabet = 'aAbBcCdDeEfFgGhHiIjJkKlLmM.nNoOpPqQrRsStTuUvVwWxXyYzZ/0123456789';	public function __construct ()	{		// Throw exception if encryption key isn't at least 8 characters long		if (mb_strlen ($this->encryptionKey, '8bit') < 8) {			throw new \Exception (				'Encryption key must by at least 8 characters long.'			);		}		// Blowfish prefix		$this->prefix = (version_compare (PHP_VERSION, '5.3.7') < 0) ? '$2a' : '$2y';		// OpenSSL raw output/options		$this->options = defined ('OPENSSL_RAW_DATA') ? OPENSSL_RAW_DATA : true;		// SHA-256 hash array		$this->encryptionHash = str_split (hash ('sha256', $this->encryptionKey));		// OpenSSL cipher IV		$this->ivSize = openssl_cipher_iv_length ($this->cipher);	}	// Creates Blowfish hash for passwords	public function createHash ($string)	{		// Alphanumeric character array		$alphabet = str_split ($this->alphabet);		// Shuffle alphanumeric character array as to randomize it		shuffle ($alphabet);		// Initial salt		$salt = '';		// Generate random 20 character alphanumeric string		foreach (array_rand ($alphabet, 20) as $character) {			$salt .= $alphabet[$character];		}		// Blowfish hash		$hash = crypt ($string, $this->prefix . $this->cost . $salt . '$$');		// Return hashed string		return $hash;	}	// Creates Blowfish hash with salt from supplied hash	public function verifyHash ($string, $compare)	{		// Split string by dollar sign		$parts = explode ('$', $compare);		// Hash salt		$salt = !empty ($parts[3]) ? $parts[3] : '';		// Encryption string as Blowfish hash		$hash = crypt ($string, $this->prefix . $this->cost . $salt . '$$');		// Returns true if both match		return ($hash === $compare);	}	// Generates a random encryption key	protected function createKey ($string)	{		// Shuffle alphanumeric character array as to randomize it		shuffle ($string);		// Initial array keys		$keys = array ();		// Initial key		$encryption_key = '';		// Generate random string from encryption key SHA-256 hash		for ($k = 0; $k < 16; $k++) {			// Add encryption key character index to keys array			$keys[] = array_search ($string[$k], $this->encryptionHash);			// Add encryption key character to key			$encryption_key .= $string[$k];		}		// Convert encryption hash array keys to string		$list = join (',', $keys);		// Return encryption key info		return array (			// Randomly generated encryption key			'key' => $encryption_key,			// List of encryption hash array keys			'keys' => $list		);	}	// OpenSSL encrypt with random key from SHA-256 hash for e-mails	public function encrypt ($string)	{		// Get a random encryption key		$key_pair = $this->createKey ($this->encryptionHash);		// Get pseudo-random bytes for OpenSSL IV		$iv = openssl_random_pseudo_bytes ($this->ivSize);		// OpenSSL encrypt using random encryption key		$encrypted = openssl_encrypt (			// String being encrypted			$string,			// Encryption cipher method			$this->cipher,			// Generated encryption key			$key_pair['key'],			// OpenSSL options			$this->options,			// Initialization vector			$iv		);		// Encode encrypted text as base64		$encoded = base64_encode ($iv . $encrypted);		// Return encryption info		return array (			// Encrypted string			'encrypted' => $encoded,			// List of encryption hash array keys			'keys' => $key_pair['keys']		);	}	// Decrypt OpenSSL encrypted string	public function decrypt ($string, $keys)	{		// Return false if string or keys is empty		if (empty ($string) or empty ($keys)) {			return false;		}		// Initial key		$decryption_key = '';		// Split keys string into array		$keys = explode (',', $keys);		// Retrieve random key from array		foreach ($keys as $value) {			// Cast key to integer			$hash_key = (int)($value);			// Check if encryption hash key exists			if (isset ($this->encryptionHash[$hash_key])) {				// If so, add character to decryption key				$decryption_key .= $this->encryptionHash[$hash_key];			} else {				// If not, give up and return false				return false;			}		}		// Decode base64 encoded string		$decoded = base64_decode ($string, true);		// Get length of decoded string		$length = mb_strlen ($decoded, '8bit');		// Get decipher text from decoded string		$decrypted = mb_substr ($decoded, $this->ivSize, $length, '8bit');		// Setup OpenSSL IV		$iv = mb_substr ($decoded, 0, $this->ivSize, '8bit');		// Return OpenSSL decrypted string		return openssl_decrypt (			// String being decrypted			$decrypted,			// Encryption decipher method			$this->cipher,			// Retrieved decryption key			$decryption_key,			// OpenSSL options			$this->options,			// Initialization vector			$iv		);	}}