<?php

class Encryption
{

	protected $encryptMethod = 'AES-256-CBC';

	/**
     * Decrypt string.
     */
	public function decrypt($encryptedString, $key)
	{
		// Sanitize the encryption key to ensure it's a safe string
		$key = sanitize_text_field($key);

		// Decode the encrypted string from base64
		$json = json_decode(base64_decode($encryptedString), true);
		
		try {
			$salt = hex2bin($json["salt"]);
			$iv = hex2bin($json["iv"]);
		} catch (Exception $e) {
			return null; // Return null if decryption fails
		}

		$cipherText = base64_decode($json['ciphertext']);
		$iterations = intval(abs($json['iterations']));
		if ($iterations <= 0) {
			$iterations = 999;
		}

		// Create hash key from password and salt using PBKDF2
		$hashKey = hash_pbkdf2('sha512', $key, $salt, $iterations, ($this->encryptMethodLength() / 4));	
		
		unset($iterations, $json, $salt);	

		// Decrypt the ciphertext using openssl_decrypt
		$decrypted = openssl_decrypt($cipherText, $this->encryptMethod, hex2bin($hashKey), OPENSSL_RAW_DATA, $iv);
		unset($cipherText, $hashKey, $iv);

		// Return decrypted string
		return $decrypted;
	}// decrypt

	/**
     * Encrypt string.
     */
	public function encrypt($string, $key)
	{
		// Sanitize the encryption key and string before using it
		$key = sanitize_text_field($key);
		$string = sanitize_textarea_field($string);

		// Get the length of the initialization vector
		$ivLength = openssl_cipher_iv_length($this->encryptMethod);
		$iv = openssl_random_pseudo_bytes($ivLength);

		// Generate salt and iterations
		$salt = openssl_random_pseudo_bytes(256);
		$iterations = 999;
		$hashKey = hash_pbkdf2('sha512', $key, $salt, $iterations, ($this->encryptMethodLength() / 4));

		// Encrypt the string using openssl_encrypt
		$encryptedString = openssl_encrypt($string, $this->encryptMethod, hex2bin($hashKey), OPENSSL_RAW_DATA, $iv);

		// Base64 encode the encrypted string and prepare the result
		$encryptedString = base64_encode($encryptedString);
		unset($hashKey);

		$output = [
			'ciphertext' => $encryptedString,
			'iv' => bin2hex($iv),
			'salt' => bin2hex($salt),
			'iterations' => $iterations
		];
		unset($encryptedString, $iterations, $iv, $ivLength, $salt);

		// Return the encrypted data as base64-encoded JSON
		return base64_encode(json_encode($output));
	}// encrypt

	/**
     * Get encrypt method length number (128, 192, 256).
     * 
     * @return integer.
     */
	protected function encryptMethodLength()
	{
		$number = filter_var($this->encryptMethod, FILTER_SANITIZE_NUMBER_INT);
		$number = intval($number);
		if($number < 0){
			$number = $number * -1;
		}
		return $number;
	}// encryptMethodLength

	/**
     * Set encryption method.
     */
	public function setCipherMethod($cipherMethod)
	{
		$this->encryptMethod = $cipherMethod;
	}// setCipherMethod

}
