/** * Generate the new key * * @param string $hash The hash algorithm to be used by HMAC * @param string $password The source password/key * @param string $salt * @param int $iterations The number of iterations * @param int $length The output size * @throws Exception\InvalidArgumentException * @return string */ public static function calc($hash, $password, $salt, $iterations, $length) { if (!Hmac::isSupported($hash)) { throw new Exception\InvalidArgumentException("The hash algorithm {$hash} is not supported by " . __CLASS__); } $num = ceil($length / Hmac::getOutputSize($hash, Hmac::OUTPUT_BINARY)); $result = ''; for ($block = 1; $block <= $num; $block++) { $hmac = hash_hmac($hash, $salt . pack('N', $block), $password, Hmac::OUTPUT_BINARY); $mix = $hmac; for ($i = 1; $i < $iterations; $i++) { $hmac = hash_hmac($hash, $hmac, $password, Hmac::OUTPUT_BINARY); $mix ^= $hmac; } $result .= $mix; } return substr($result, 0, $length); }
public function testIsSupportedAndCache() { Hmac::clearLastAlgorithmCache(); $this->assertAttributeEquals(null, 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); $algorithm = 'sha512'; // cache value must be exactly equal to the original input $this->assertTrue(Hmac::isSupported($algorithm)); $this->assertAttributeEquals($algorithm, 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); $this->assertAttributeNotEquals('sHa512', 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); // cache value must be exactly equal to the first input (cache hit) Hmac::isSupported('sha512'); $this->assertAttributeEquals($algorithm, 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); // cache changes with a new algorithm $this->assertTrue(Hmac::isSupported('MD5')); $this->assertAttributeEquals('MD5', 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); // cache don't change due wrong algorithm $this->assertFalse(Hmac::isSupported('wrong')); $this->assertAttributeEquals('MD5', 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); Hmac::clearLastAlgorithmCache(); $this->assertAttributeEquals(null, 'lastAlgorithmSupported', 'Zend\\Crypt\\Hmac'); }