1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
<?php /** * @version $Id: crypt.php 20996 2012-04-01 21:48:35Z bharat $ * @package Joomla.Platform * @subpackage Crypt * * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE */
//defined('JPATH_BASE') or die();
/** * JCrypt is a Joomla Platform class for handling basic encryption/decryption of data. * * @package Joomla.Platform * @subpackage Crypt * @since 12.1 */ class JCrypt { /** * Generate random bytes. * * @param integer $length Length of the random data to generate * * @return string Random binary data * * @since 12.1 * @note This method requires PHP 5 */ function genRandomBytes($length = 16) { $sslStr = ''; /* * if a secure randomness generator exists and we don't * have a buggy PHP version use it. */ if ( function_exists('openssl_random_pseudo_bytes') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || substr(PHP_OS, 0, 3) !== 'WIN' ) ) { $sslStr = openssl_random_pseudo_bytes($length, $strong); if ($strong) { return $sslStr; } }
/* * Collect any entropy available in the system along with a number * of time measurements of operating system randomness. */ $bitsPerRound = 2; $maxTimeMicro = 400; $shaHashLength = 20; $randomStr = ''; $total = $length;
// Check if we can use /dev/urandom. $urandom = false; $handle = null; if (function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom')) { $handle = @fopen('/dev/urandom', 'rb'); if ($handle) { $urandom = true; } }
while ($length > strlen($randomStr)) { $bytes = ($total > $shaHashLength)? $shaHashLength : $total; $total -= $bytes; /* * Collect any entropy available from the PHP system and filesystem. * If we have ssl data that isn't strong, we use it once. */ $entropy = rand() . uniqid(mt_rand(), true) . $sslStr; $entropy .= implode('', @fstat(fopen( __FILE__, 'r'))); //$entropy .= memory_get_usage(); $sslStr = ''; if ($urandom) { stream_set_read_buffer($handle, 0); $entropy .= @fread($handle, $bytes); } else { /* * There is no external source of entropy so we repeat calls * to mt_rand until we are assured there's real randomness in * the result. * * Measure the time that the operations will take on average. */ $samples = 3; $duration = 0; for ($pass = 0; $pass < $samples; ++$pass) { $microStart = microtime(true) * 1000000; $hash = sha1(mt_rand()); for ($count = 0; $count < 50; ++$count) { $hash = sha1($hash); } $microEnd = microtime(true) * 1000000; $entropy .= $microStart . $microEnd; if ($microStart > $microEnd) { $microEnd += 1000000; } $duration += $microEnd - $microStart; } $duration = $duration / $samples;
/* * Based on the average time, determine the total rounds so that * the total running time is bounded to a reasonable number. */ $rounds = (int)(($maxTimeMicro / $duration) * 50);
/* * Take additional measurements. On average we can expect * at least $bitsPerRound bits of entropy from each measurement. */ $iter = $bytes * (int) ceil(8 / $bitsPerRound); for ($pass = 0; $pass < $iter; ++$pass) { $microStart = microtime(true); $hash = sha1(mt_rand()); for ($count = 0; $count < $rounds; ++$count) { $hash = sha1($hash); } $entropy .= $microStart . microtime(true); } }
$randomStr .= sha1($entropy); }
if ($urandom) { @fclose($handle); }
return substr($randomStr, 0, $length); } }
|