diff options
Diffstat (limited to 'phpBB/phpbb/crypto/manager.php')
| -rw-r--r-- | phpBB/phpbb/crypto/manager.php | 206 | 
1 files changed, 206 insertions, 0 deletions
| diff --git a/phpBB/phpbb/crypto/manager.php b/phpBB/phpbb/crypto/manager.php new file mode 100644 index 0000000000..753a86ae84 --- /dev/null +++ b/phpBB/phpbb/crypto/manager.php @@ -0,0 +1,206 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ +	exit; +} + +/** +* @package crypto +*/ +class phpbb_crypto_manager +{ +	/** +	* Default hashing method +	*/ +	protected $type = false; + +	/** +	* Hashing algorithm types +	*/ +	protected $type_map = false; + +	/** +	* Password convert flag. Password should be converted +	*/ +	public $convert_flag = false; + +	/** +	* Crypto helper +	* @var phpbb_crypto_helper +	*/ +	protected $helper; + +	/** +	* phpBB configuration +	* @var phpbb_config +	*/ +	protected $config; + +	/** +	* phpBB compiled container +	* @var service_container +	*/ +	protected $container; + +	/** +	* Construct a crypto object +	* +	* @param phpbb_config $config phpBB configuration +	*/ +	public function __construct($config, $container, $hashing_algorithms) +	{ +		$this->config = $config; +		$this->container = $container; +		$this->type = 'crypto.driver.bcrypt_2y'; // might want to make this flexible + +		$this->fill_type_map($hashing_algorithms); +		$this->load_crypto_helper(); +	} + +	/** +	* Fill algorithm type map +	* +	* @param phpbb_di_service_collection $hashing_algorithms +	*/ +	protected function fill_type_map($hashing_algorithms) +	{ +		foreach ($hashing_algorithms as $algorithm) +		{ +			if (!isset($this->type_map[$algorithm->get_prefix()])) +			{ +				$this->type_map[$algorithm->get_prefix()] = $algorithm; +			} +		} +	} + +	/** +	* Load crypto helper class +	*/ +	protected function load_crypto_helper() +	{ +		if ($this->helper === null) +		{ +			$this->helper = new phpbb_crypto_helper($this, $this->container); +		} +	} + +	/** +	* Get the hash type from the supplied hash +	* +	* @param string $hash Password hash that should be checked +	* +	* @return object The hash type object +	*/ +	public function get_hashing_algorithm($hash) +	{ +		/* +		* preg_match() will also show hashing algos like $2a\H$, which +		* is a combination of bcrypt and phpass. Legacy algorithms +		* like md5 will not be matched by this and need to be treated +		* differently. +		*/ +		if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) +		{ +			return $this->type_map['$H$']; +		} + +		// Be on the lookout for multiple hashing algorithms +		// 2 is correct: H\2a > 2, H\P > 2 +		if (strlen($match[1]) > 2) +		{ +			$hash_types = explode('\\', $match[1]); +			$return_ary = array(); +			foreach ($hash_types as $type) +			{ +				if (isset($this->type_map["\${$type}\$"])) +				{ +					// we do not support the same hashing +					// algorithm more than once +					if (isset($return_ary[$type])) +					{ +						return false; +					} +					$return_ary[$type] = $this->type_map["\${$type}\$"]; +				} +				else +				{ +					return false; +				} +			} +			return $return_ary; +		} +		if (isset($this->type_map[$match[0]])) +		{ +			return $this->type_map[$match[0]]; +		} +		else +		{ +			return false; +		} +	} + +	/** +	* Hash supplied password +	* +	* @param string $password Password that should be hashed +	* @param string $type Hash type. Will default to standard hash type if +	*			none is supplied +	* @return string|bool Password hash of supplied password or false if +	*			if something went wrong during hashing +	*/ +	public function hash_password($password, $type = '') +	{ +		$type = ($type === '') ? $this->type : $type; + +		if (is_array($type)) +		{ +			return $this->helper->combined_hash_password($password, $type); +		} + +		$hashing_algorithm = $this->container->get($type); +		// Do not support 8-bit characters with $2a$ bcrypt +		if ($type === 'crypto.driver.bcrypt' || ($type === 'crypto.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) +		{ +			if (ord($password[strlen($password)-1]) & 128) +			{ +				return false; +			} +		} + +		return $this->container->get($type)->hash($password); +	} + +	public function check_hash($password, $hash) +	{ +		// First find out what kind of hash we're dealing with +		$stored_hash_type = $this->get_hashing_algorithm($hash); +		if ($stored_hash_type == false) +		{ +			return false; +		} + +		// Multiple hash passes needed +		if (is_array($stored_hash_type)) +		{ +			return $this->helper->check_combined_hash($password, $stored_hash_type, $hash); +		} + +		if ($stored_hash_type->get_type() !== $this->type) +		{ +			$this->convert_flag = true; +		} + +		return $stored_hash_type->check($password, $hash); +	} +} | 
