. * */ defined('APP_ROOT') || die(_('No es posible acceder directamente a este archivo')); /** * Esta clase es la encargada de realizar el encriptad/desencriptado de claves */ class SP_Crypt { public $strInitialVector; /** * @brief Crear el vector de inicialización * @return string con el IV */ private static function createIV() { $resEncDes = mcrypt_module_open('rijndael-256', '', 'cbc', ''); if ( SP_Util::runningOnWindows() && (! defined('PHP_VERSION_ID') || PHP_VERSION_ID < 50300) ){ $cryptIV = mcrypt_create_iv(mcrypt_enc_get_iv_size($resEncDes), MCRYPT_RAND); } else { $cryptIV = mcrypt_create_iv(mcrypt_enc_get_iv_size($resEncDes), MCRYPT_DEV_URANDOM); } mcrypt_module_close($resEncDes); return $cryptIV; } /** * @brief Comprobar si el vector de inicialización tiene la longitud correcta * @param string $cryptIV con el IV * @return bool */ private static function checkIV($cryptIV){ $strEscapeInitialVector = DB::escape($cryptIV); if (strlen($strEscapeInitialVector) != 32 ) { return FALSE; } else { return TRUE; } } /** * @brief Encriptar datos con la clave maestra * @param string $strValue con los datos a encriptar * @param string $strPassword con la clave maestra * @param string $cryptIV con el IV * @return string con los datos encriptados */ private function encrypt($strValue, $strPassword, $cryptIV){ $resEncDes = mcrypt_module_open('rijndael-256', '', 'cbc', ''); mcrypt_generic_init($resEncDes, $strPassword, $cryptIV); $strEncrypted = mcrypt_generic($resEncDes, $strValue); mcrypt_generic_deinit($resEncDes); return $strEncrypted; } /** * @brief Desencriptar datos con la clave maestra * @param string $strEncrypted con los datos a desencriptar * @param string $strPassword con la clave maestra * @param string $cryptIV con el IV * @return string con los datos desencriptados */ public function decrypt($strEncrypted, $strPassword, $cryptIV){ $resEncDes = mcrypt_module_open('rijndael-256', '', 'cbc', ''); mcrypt_generic_init($resEncDes, $strPassword, $cryptIV); $strDecrypted = trim(mdecrypt_generic($resEncDes, $strEncrypted)); mcrypt_generic_deinit($resEncDes); mcrypt_module_close($resEncDes); return $strDecrypted; } /** * @brief Comprobar si el módulo de encriptación está disponible * @param string $strEncrypted con los datos a desencriptar * @param string $strPassword con la clave maestra * @param string $cryptIV con el IV * @return string con los datos desencriptados */ public static function checkCryptModule(){ $resEncDes = mcrypt_module_open('rijndael-256', '', 'cbc', ''); if ($resEncDes == FALSE ) { return FALSE; } else { return TRUE; } } /** * @brief Comprobar datos encriptados * @param string $strEncryptedPass con los datos encriptados * @return bool * * Esta función comprueba la longitud de los datos encriptados despues de * escaparlos con mysqli */ private function checkEncryptedPass($strEncryptedPass){ $strEscapedEncryptedPass = DB::escape($strEncryptedPass); if (strlen($strEscapedEncryptedPass) != strlen($strEncryptedPass) ) { return FALSE; } else { return TRUE; } } /** * @brief Generar una clave encriptada * @param string $pwd con la clave a encriptar * @param string $masterPwd con la clave maestra * @return bool * * Esta función llama a los métodos privados para encriptar datos. */ public function mkEncrypt($pwd,$masterPwd = ""){ $masterPwd = ( ! $masterPwd ) ? $this->getSessionMasterPass() : $masterPwd; do { do { $cryptIV = SP_Crypt::createIV(); $blnCheckIv = SP_Crypt::checkIV($cryptIV); } while ($blnCheckIv == FALSE); $this->strInitialVector = $cryptIV; $cryptValue = $this->encrypt($pwd, $masterPwd, $cryptIV); $blnCheckEncrypted = $this->checkEncryptedPass($cryptValue); } while ($blnCheckEncrypted == FALSE ); return $cryptValue; } /** * @brief Generar la clave maestra encriptada con la clave del usuario * @param string $customPwd con la clave a encriptar * @param string $masterPwd con la clave maestra * @return string con la clave encriptada * * Esta función llama a los métodos privados para encriptar datos. */ public function mkCustomMPassEncrypt($customPwd,$masterPwd){ do { do { $cryptIV = SP_Crypt::createIV(); $blnCheckIv = SP_Crypt::CheckIV($cryptIV); } while ($blnCheckIv == FALSE); $cryptValue = $this->encrypt($masterPwd, $customPwd, $cryptIV); $blnCheckEncrypted = $this->checkEncryptedPass($cryptValue); } while ($blnCheckEncrypted == FALSE ); $dataCrypt = array($cryptValue, $cryptIV); return $dataCrypt; } /** * @brief Generar un hash de una clave utilizando un salt * @param string $pwd con la clave a 'hashear' * @return string con el hash de la clave */ public static function mkHashPassword($pwd){ $salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); // Obtenemos 256 bits aleatorios en hexadecimal $hash = hash("sha256", $salt.$pwd); // Añadimos el salt a la clave y rehacemos el hash $hashPwd = $salt.$hash; return $hashPwd; } /** * @brief Comprobar el hash de una clave * @param string $pwd con la clave a comprobar * @param string $correctHash con el hash a comprobar * @return bool */ public static function checkHashPass($pwd, $correctHash){ // Obtenemos el salt de la clave $salt = substr($correctHash, 0, 64); // Obtenemos el hash SHA256 $validHash = substr($correctHash, 64, 64); // Re-hash de la clave a comprobar $testHash = hash("sha256", $salt . $pwd); // Si los hashes son idénticos, la clave es válida if ( $testHash === $validHash ){ return TRUE; } return FALSE; } /** * @brief Crear un salt * @return string con el salt creado */ public static function makeHashSalt(){ do { $cryptIV = self::createIV(); $blnCheckIv = self::checkIV($cryptIV); } while ($blnCheckIv == FALSE); return $cryptIV; } /** * @brief Desencriptar la clave maestra de la sesión * @return string con la clave maestra */ public function getSessionMasterPass(){ return $this->decrypt($_SESSION["mPass"], $_SESSION['mPassPwd'], $_SESSION['mPassIV']); } }