<?php
class DeterministicRandom
{
protected $counter;
public function __construct(string $seed = '', int $counter = 0)
{
$this->seed('set', $seed);
$this->counter = 0;
}
private function seed(string $action = 'get', string $data = '')
{
static $seed = null;
if ($action === 'set') {
$seed = $data;
} elseif ($action === 'get') {
return $data;
} else {
throw new \Error(
'Unknown action'
);
}
}
public function getBytes(int $numBytes): string
{
return \openssl_encrypt(
\str_repeat("\0", $numBytes),
'aes-128-ctr',
$this->seed('get'),
OPENSSL_RAW_DATA,
$this->getNonce($numBytes)
);
}
public function getInt(int $min, int $max): int
{
/**
* @todo
*/
return 0;
}
protected function getNonce(int $increment = 0): string
{
$nonce = '';
$ctr = $this->counter;
while ($ctr > 0) {
$nonce = \chr($ctr & 0xFF) . $nonce;
$ctr >>= 8;
}
$this->counter += $increment;
return \str_pad($nonce, 16, "\0", STR_PAD_LEFT);
}
}
$seed = str_repeat("\x80", 16);
$rnd1 = new DeterministicRandom($seed);
$rnd2 = new DeterministicRandom($seed);
$out1 = $rnd1->getBytes(16);
$out2 = $rnd1->getBytes(16);
$out3 = $rnd2->getBytes(32);
var_dump([
bin2hex($out1),
bin2hex($out2),
bin2hex($out3)
]);
preferences:
45.35 ms | 402 KiB | 5 Q