<?php
require_once "/main.inc";

class Encryption
{
	public $publicKey=null;
	public $privateKey=null;
	private $res=null;
	private $dt=null;
	
	private $psk=null;
	private $upsk=false;
	
	private static $sklen = 4096;
	
	private static $config = array(
		"digest_alg" => "sha512",
		"private_key_bits" => 4096,
		"private_key_type"=> OPENSSL_KEYTYPE_RSA,
	);
	private function generateNewSymmetricKey()
	{
		return openssl_random_pseudo_bytes(self::$sklen);
	}
	private function _begin($prec)
	{
		$this->res = openssl_pkey_new(self::$config);
		openssl_pkey_export($this->res, $this->publicKey);
		$this->dt=openssl_pkey_get_details($this->res);
		$this->publicKey=$this->dt["key"];
		
		if($prec)
		{
			$this->upsk = true;
			$this->psk = generateNewSymmetricKey();
		}
	}
	public function __construct()
	{
		$this->_begin(false);
	}
	public function __construct1($p)
	{
		$this->_begin($p);
	}
	private function s_decrypt($data, $key)
	{
		return s_encrypt($data, $key); //same;
	}
	private function s_encrypt($data, $key)
	{
		$j=0;
		$out = "";
		for($i=0;$i<strlen($data);$i++)
		{
			if($j>=strlen($key)) $j=0;
			$out .= ($data[$i] ^ $key[$j]);
			$j+=1;
		}
		return $out;
	}
	
	public function encrypt($data)
	{
		$skey = ($this->upsk?$this->psk:$this->generateNewSymmetricKey());
		$e_skey = null;
		openssl_public_encrypt($skey, $e_skey, $this->publicKey);
		
		$e_data = $this->s_encrypt($data, $skey);
		
		return CreateFromEncryption(array("ekey"=>$e_skey, "edata"=>$e_data));
	}
	public function decrypt(EncryptedData $ed)
	{
		$ekey = $ed->e_symmetricKey();
		$edata = $ed->e_data();
		
		$skey = null;
		openssl_private_decrypt($ekey, $skey, $this->privateKey);
		return $this->s_decrypt($edata, $skey);
	}
	public function encdata_create($data)
	{
		return EncryptedData::CreateFromData($data);
	}
}
class EncryptedData
{
	private $ekey=null;
	private $edata=null;
	private function __construct(Array $data)
	{
		$this->ekey = $data["ekey"];
		$this->edata = $data["edata"];
	}
	public function __construct1($ek, $ed)
	{
		$this->ekey = $ek;
		$this->edata = $ed;
	}
	private function __construct2()
	{
		
	}
	public function binaryData($set=null)
	{
		if($set==null) {
			return "{".strlen($this->ekey).", ".strlen($this->edata)."}".$this->ekey.$this->edata;
		}
		else
		{
			$kvals = explode(", ", substr(substr($set, 0, strpos($set, "}")), 1));
			$klen = intval($kvals[0]);
			$dlen = intval($kvals[1]);
			
			$this->ekey = substr($set, strpos($set, "}")+1, $klen);
			$this->edata = substr($set, strpos($set, "}")+1+$klen, $dlen);
		}
	}
	public function e_symmetricKey($val=null)
	{
		if($val==null) {
			return $this->ekey;
		}
		else
		{
			$this->ekey = $val;
		}
	}
	public function e_data($val=null)
	{
		if($val==null) {
			return $this->edata;
		}
		else
		{
			$this->edata = $val;
		}
	}
	public static function CreateFromData($data)
	{
		$val = new EncryptedData();
		$val->binaryData($data);
		return $val;
	}
	public static function CreateFromEncryption(Array $data)
	{
		return new EncryptedData($data);
	}
}

?>