public function testHashLength() { if (MWCryptHash::hashAlgo() !== 'whirlpool') { $this->markTestSkipped('Hash algorithm isn\'t whirlpool'); } $this->assertEquals(64, MWCryptHash::hashLength(), 'Raw hash length'); $this->assertEquals(128, MWCryptHash::hashLength(false), 'Hex hash length'); }
/** * Randomly hash data while mixing in clock drift data for randomness * * @param string $data The data to randomly hash. * @return string The hashed bytes * @author Tim Starling */ protected function driftHash($data) { // Minimum number of iterations (to avoid slow operations causing the // loop to gather little entropy) $minIterations = self::MIN_ITERATIONS; // Duration of time to spend doing calculations (in seconds) $duration = self::MSEC_PER_BYTE / 1000 * MWCryptHash::hashLength(); // Create a buffer to use to trigger memory operations $bufLength = 10000000; $buffer = str_repeat(' ', $bufLength); $bufPos = 0; // Iterate for $duration seconds or at least $minIterations number of iterations $iterations = 0; $startTime = microtime(true); $currentTime = $startTime; while ($iterations < $minIterations || $currentTime - $startTime < $duration) { // Trigger some memory writing to trigger some bus activity // This may create variance in the time between iterations $bufPos = ($bufPos + 13) % $bufLength; $buffer[$bufPos] = ' '; // Add the drift between this iteration and the last in as entropy $nextTime = microtime(true); $delta = (int) (($nextTime - $currentTime) * 1000000); $data .= $delta; // Every 100 iterations hash the data and entropy if ($iterations % 100 === 0) { $data = sha1($data); } $currentTime = $nextTime; $iterations++; } $timeTaken = $currentTime - $startTime; $data = MWCryptHash::hash($data); wfDebug(__METHOD__ . ": Clock drift calculation " . "(time-taken=" . $timeTaken * 1000 . "ms, " . "iterations={$iterations}, " . "time-per-iteration=" . $timeTaken / $iterations * 1000000.0 . "us)\n"); return $data; }