|
13 | 13 |
|
14 | 14 | @trigger_error('The '.__NAMESPACE__.'\SecureRandom class is deprecated since version 2.8 and will be removed in 3.0. Use the random_bytes function instead.', E_USER_DEPRECATED);
|
15 | 15 |
|
16 |
| -use Psr\Log\LoggerInterface; |
17 |
| - |
18 | 16 | /**
|
19 | 17 | * A secure random number generator implementation.
|
20 | 18 | *
|
|
25 | 23 | */
|
26 | 24 | final class SecureRandom implements SecureRandomInterface
|
27 | 25 | {
|
28 |
| - private $logger; |
29 |
| - private $useOpenSsl; |
30 |
| - private $seed; |
31 |
| - private $seedUpdated; |
32 |
| - private $seedLastUpdatedAt; |
33 |
| - private $seedFile; |
34 |
| - |
35 |
| - /** |
36 |
| - * Constructor. |
37 |
| - * |
38 |
| - * Be aware that a guessable seed will severely compromise the PRNG |
39 |
| - * algorithm that is employed. |
40 |
| - * |
41 |
| - * @param string $seedFile |
42 |
| - * @param LoggerInterface $logger |
43 |
| - */ |
44 |
| - public function __construct($seedFile = null, LoggerInterface $logger = null) |
45 |
| - { |
46 |
| - $this->seedFile = $seedFile; |
47 |
| - $this->logger = $logger; |
48 |
| - |
49 |
| - // determine whether to use OpenSSL |
50 |
| - if (!function_exists('random_bytes') && !function_exists('openssl_random_pseudo_bytes')) { |
51 |
| - if (null !== $this->logger) { |
52 |
| - $this->logger->notice('It is recommended that you install the "paragonie/random_compat" library or enable the "openssl" extension for random number generation.'); |
53 |
| - } |
54 |
| - $this->useOpenSsl = false; |
55 |
| - } else { |
56 |
| - $this->useOpenSsl = true; |
57 |
| - } |
58 |
| - } |
59 |
| - |
60 | 26 | /**
|
61 | 27 | * {@inheritdoc}
|
62 | 28 | */
|
63 | 29 | public function nextBytes($nbBytes)
|
64 | 30 | {
|
65 |
| - if (function_exists('random_bytes')) { |
66 |
| - return random_bytes($nbBytes); |
67 |
| - } |
68 |
| - |
69 |
| - // try OpenSSL |
70 |
| - if ($this->useOpenSsl) { |
71 |
| - $bytes = openssl_random_pseudo_bytes($nbBytes, $strong); |
72 |
| - |
73 |
| - if (false !== $bytes && true === $strong) { |
74 |
| - return $bytes; |
75 |
| - } |
76 |
| - |
77 |
| - if (null !== $this->logger) { |
78 |
| - $this->logger->info('OpenSSL did not produce a secure random number.'); |
79 |
| - } |
80 |
| - } |
81 |
| - |
82 |
| - // initialize seed |
83 |
| - if (null === $this->seed) { |
84 |
| - if (null === $this->seedFile) { |
85 |
| - throw new \RuntimeException('You need to specify a file path to store the seed.'); |
86 |
| - } |
87 |
| - |
88 |
| - if (is_file($this->seedFile)) { |
89 |
| - list($this->seed, $this->seedLastUpdatedAt) = $this->readSeed(); |
90 |
| - } else { |
91 |
| - $this->seed = uniqid(mt_rand(), true); |
92 |
| - $this->updateSeed(); |
93 |
| - } |
94 |
| - } |
95 |
| - |
96 |
| - $bytes = ''; |
97 |
| - while (strlen($bytes) < $nbBytes) { |
98 |
| - static $incr = 1; |
99 |
| - $bytes .= hash('sha512', $incr++.$this->seed.uniqid(mt_rand(), true).$nbBytes, true); |
100 |
| - $this->seed = base64_encode(hash('sha512', $this->seed.$bytes.$nbBytes, true)); |
101 |
| - $this->updateSeed(); |
102 |
| - } |
103 |
| - |
104 |
| - return substr($bytes, 0, $nbBytes); |
105 |
| - } |
106 |
| - |
107 |
| - private function readSeed() |
108 |
| - { |
109 |
| - return json_decode(file_get_contents($this->seedFile)); |
110 |
| - } |
111 |
| - |
112 |
| - private function updateSeed() |
113 |
| - { |
114 |
| - if (!$this->seedUpdated && $this->seedLastUpdatedAt < time() - mt_rand(1, 10)) { |
115 |
| - file_put_contents($this->seedFile, json_encode(array($this->seed, microtime(true)))); |
116 |
| - } |
117 |
| - |
118 |
| - $this->seedUpdated = true; |
| 31 | + return random_bytes($nbBytes); |
119 | 32 | }
|
120 | 33 | }
|
0 commit comments