/** * Finish the hashing of a partially hashed layered hash * * Given a password hash that is hashed using the first layer of this object's * configuration, perform the remaining layers of password hashing in order to * get an updated hash with all the layers. * * @param ParameterizedPassword $passObj Password hash of the first layer * * @throws MWException If the first parameter is not of the correct type */ public function partialCrypt(ParameterizedPassword $passObj) { $type = $passObj->config['type']; if ($type !== $this->config['types'][0]) { throw new MWException('Only a hash in the first layer can be finished.'); } // Gather info from the existing hash $this->params[0] = implode($passObj->getDelimiter(), $passObj->params); $this->args[0] = implode($passObj->getDelimiter(), $passObj->args); $lastHash = $passObj->hash; // Layer the remaining types foreach ($this->config['types'] as $i => $type) { if ($i == 0) { continue; } // Construct pseudo-hash based on params and arguments /** @var ParameterizedPassword $passObj */ $passObj = $this->factory->newFromType($type); $params = ''; $args = ''; if ($this->params[$i] !== '') { $params = $this->params[$i] . $passObj->getDelimiter(); } if (isset($this->args[$i]) && $this->args[$i] !== '') { $args = $this->args[$i] . $passObj->getDelimiter(); } $existingHash = ":{$type}:" . $params . $args . $this->hash; // Hash the last hash with the next type in the layer $passObj = $this->factory->newFromCiphertext($existingHash); $passObj->crypt($lastHash); // Move over the params and args $this->params[$i] = implode($passObj->getDelimiter(), $passObj->params); $this->args[$i] = implode($passObj->getDelimiter(), $passObj->args); $lastHash = $passObj->hash; } $this->hash = $lastHash; }
protected function parseHash($hash) { parent::parseHash($hash); $this->params['rounds'] = (int) $this->params['rounds']; }