<?php

class pasw
{
	private $vLongMaxi = 40;
	private $vEncrAlgo = MCRYPT_TRIPLEDES;
	private $vEncrModo = "cbc";
	private $vClavStrn = "very secret key";
	private $aCharTerm = array('|','°','¬','!','#','$','%','&','(',')','=',				// array de caracteres marcan el final de la contraseña.
	'?','¿','¡');
	private $aCharExcl = array(0, 10, 13, 39);																		// Cod ascii de caracteres que no deben estar en la contraseña
	
	public $vEncrDesc = null;																											// encryption descriptor
	public $vInveSize = null;																											// Tamaño del IV
	public $vInicVect = null;																											// Vector de inicializacion (iv)
	public $vClavSize = null;
	public $vClavEncr = null;																											// clave encriptada.
	public $vDatoEncr = null;																											// dato encriptado
	public $vDatoDEnc = null;																											// dato des-encriptado
	
	private function inicializar() {
		$this->vEncrDesc = mcrypt_module_open($this->vEncrAlgo,'',$this->vEncrModo,''); // abrir el modulo del algoritmo y el modo de uso.
		$this->vInveSize = mcrypt_enc_get_iv_size($this->vEncrDesc);	              // obtengo el tamaño del iv.
		$this->vClavSize = mcrypt_enc_get_key_size( $this->vEncrDesc );             // obtengo el tamaño de la clave soportado por el modo abierto
		$this->vClavEncr = substr(md5( $this->vClavStrn ), 0, $this->vClavSize);    // creacion de la clave
	}
	
	private function liberar() {
		mcrypt_generic_deinit( $this->vEncrDesc );                                  // Terminar el manejador de la encriptacion
		mcrypt_module_close($this->vEncrDesc);
	}
	
	public function encriptar ( $dato ) {                                         // creacion de la contraseña
		if ( strlen($dato) <= $this->vLongMaxi )																		// controlo la longitud de la contraseña ingresada
		{
			do {																																			// se repetiran los pasos hasta obtener un contraseña sin errores.
				$this->inicializar();
				$this->vInicVect = mcrypt_create_iv( $this->vInveSize, MCRYPT_RAND);    // obtengo vector de inicializacion
				mcrypt_generic_init($this->vEncrDesc,$this->vClavEncr,$this->vInicVect);// Intialize encryption: inicializa buffer para la encriptacion
				$this->vDatoEncr = mcrypt_generic($this->vEncrDesc, $dato);             // Encriptar informacion
				$this->liberar();                                                       // Terminar el manejador de la encriptacion
				$r = $this->getDatoEncriptado();                                        // devolver dato encriptado
			} while ( $this->ctrlCaracExcl( $r ) );																		// valida que la contraseña no tenga caracteres prohibidos.
			return $r;
		}
		else
		{
			return false;
		}
	}
	
	private function ctrlCaracExcl( $enc ) {
		$aC = str_split( $enc );																										// armo un array con todos los caracteres de la contraseña
		foreach( $aC as $k => $v )
			if ( in_array( ord($v), $this->aCharExcl ) )															// si el codigo ascii de algun caracter esta en el array
				return true;																														// existe caracter excluido
		return false;																																// no existe caracter excluido.
	} 
	
	private function desencriptar ( $dato ) {
		if ( $dato === false) 
		{
			return false;
		}
		else
		{
			$this->inicializar();                                                     //var_dump($dato);
			$iv = substr( substr($dato, -1*($this->vInveSize+1) ), 0, $this->vInveSize ); // IV utilizado en la encriptacion se encuentra en el dato a desencriptar
			mcrypt_generic_init($this->vEncrDesc, $this->vClavEncr, $iv);             // Intialize encryption: inicializa el buffer necesario para la encriptacion
			$dato = substr( $dato, 0, strlen($dato)-($this->vInveSize+1) );           // Decrypt encrypted string	
			$this->vDatoDEnc = trim(mdecrypt_generic($this->vEncrDesc, $dato));
			$this->liberar();                                                         // Terminar el manejador de la encriptacion 
			return $this->getDatoDesencriptado ();                                    // devolver dato desencriptado
		}
	}
	
	public function comparar ( $input, $pwdenc ) {
		$t = substr($pwdenc, -1);                                                   // si no existe alguno de los caracteres finales de las contraseña, es pq 
		if ( in_array($t, $this->aCharTerm) )                                       // la contraseña no se encuentra encriptada.
			$r = $this->desencriptar( $pwdenc );
		else
			$r = $pwdenc;
		if ( $input === $r )
			return true;
		else
			return false;
	}
	
	private function getDatoEncriptado () {
		$i = rand( 0, count( $this->aCharTerm )-1 );
		return $this->vDatoEncr.$this->vInicVect.$this->aCharTerm[$i];
	}
	
	private function getDatoDesencriptado () {
		return $this->vDatoDEnc;
	}
}

?>