33 * Portable PHP password hashing framework.
44 * @package phpass
55 * @since 2.5.0
6- * @version 0.3 / WordPress
6+ * @version 0.5 / WordPress
77 * @link https://www.openwall.com/phpass/
88 */
99
10+ #
11+ # Portable PHP password hashing framework.
12+ #
13+ # Version 0.5 / WordPress.
1014#
1115# Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
1216# the public domain. Revised in subsequent years, still public domain.
1317#
1418# There's absolutely no warranty.
1519#
20+ # The homepage URL for this framework is:
21+ #
22+ # http://www.openwall.com/phpass/
23+ #
1624# Please be sure to update the Version line if you edit this file in any way.
1725# It is suggested that you leave the main version number intact, but indicate
1826# your project name (after the slash) and add your own revision information.
2937 * Portable PHP password hashing framework.
3038 *
3139 * @package phpass
32- * @version 0.3 / WordPress
40+ * @version 0.5 / WordPress
3341 * @link https://www.openwall.com/phpass/
3442 * @since 2.5.0
3543 */
@@ -39,10 +47,7 @@ class PasswordHash {
3947 var $ portable_hashes ;
4048 var $ random_state ;
4149
42- /**
43- * PHP5 constructor.
44- */
45- function __construct ( $ iteration_count_log2 , $ portable_hashes )
50+ function __construct ($ iteration_count_log2 , $ portable_hashes )
4651 {
4752 $ this ->itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' ;
4853
@@ -52,20 +57,20 @@ function __construct( $iteration_count_log2, $portable_hashes )
5257
5358 $ this ->portable_hashes = $ portable_hashes ;
5459
55- $ this ->random_state = microtime () . uniqid (rand (), TRUE ); // removed getmypid() for compatibility reasons
60+ $ this ->random_state = microtime ();
61+ if (function_exists ('getmypid ' ))
62+ $ this ->random_state .= getmypid ();
5663 }
5764
58- /**
59- * PHP4 constructor.
60- */
61- public function PasswordHash ( $ iteration_count_log2 , $ portable_hashes ) {
62- self ::__construct ( $ iteration_count_log2 , $ portable_hashes );
65+ function PasswordHash ($ iteration_count_log2 , $ portable_hashes )
66+ {
67+ self ::__construct ($ iteration_count_log2 , $ portable_hashes );
6368 }
6469
6570 function get_random_bytes ($ count )
6671 {
6772 $ output = '' ;
68- if ( @is_readable ('/dev/urandom ' ) &&
73+ if (@is_readable ('/dev/urandom ' ) &&
6974 ($ fh = @fopen ('/dev/urandom ' , 'rb ' ))) {
7075 $ output = fread ($ fh , $ count );
7176 fclose ($ fh );
@@ -76,8 +81,7 @@ function get_random_bytes($count)
7681 for ($ i = 0 ; $ i < $ count ; $ i += 16 ) {
7782 $ this ->random_state =
7883 md5 (microtime () . $ this ->random_state );
79- $ output .=
80- pack ('H* ' , md5 ($ this ->random_state ));
84+ $ output .= md5 ($ this ->random_state , TRUE );
8185 }
8286 $ output = substr ($ output , 0 , $ count );
8387 }
@@ -121,12 +125,12 @@ function gensalt_private($input)
121125 function crypt_private ($ password , $ setting )
122126 {
123127 $ output = '*0 ' ;
124- if (substr ($ setting , 0 , 2 ) == $ output )
128+ if (substr ($ setting , 0 , 2 ) === $ output )
125129 $ output = '*1 ' ;
126130
127131 $ id = substr ($ setting , 0 , 3 );
128132 # We use "$P$", phpBB3 uses "$H$" for the same thing
129- if ($ id != '$P$ ' && $ id != '$H$ ' )
133+ if ($ id !== '$P$ ' && $ id != = '$H$ ' )
130134 return $ output ;
131135
132136 $ count_log2 = strpos ($ this ->itoa64 , $ setting [3 ]);
@@ -136,51 +140,26 @@ function crypt_private($password, $setting)
136140 $ count = 1 << $ count_log2 ;
137141
138142 $ salt = substr ($ setting , 4 , 8 );
139- if (strlen ($ salt ) != 8 )
143+ if (strlen ($ salt ) !== 8 )
140144 return $ output ;
141145
142- # We're kind of forced to use MD5 here since it's the only
143- # cryptographic primitive available in all versions of PHP
144- # currently in use. To implement our own low-level crypto
145- # in PHP would result in much worse performance and
146+ # We were kind of forced to use MD5 here since it's the only
147+ # cryptographic primitive that was available in all versions
148+ # of PHP in use. To implement our own low-level crypto in PHP
149+ # would have resulted in much worse performance and
146150 # consequently in lower iteration counts and hashes that are
147151 # quicker to crack (by non-PHP code).
148- if (PHP_VERSION >= '5 ' ) {
149- $ hash = md5 ($ salt . $ password , TRUE );
150- do {
151- $ hash = md5 ($ hash . $ password , TRUE );
152- } while (--$ count );
153- } else {
154- $ hash = pack ('H* ' , md5 ($ salt . $ password ));
155- do {
156- $ hash = pack ('H* ' , md5 ($ hash . $ password ));
157- } while (--$ count );
158- }
152+ $ hash = md5 ($ salt . $ password , TRUE );
153+ do {
154+ $ hash = md5 ($ hash . $ password , TRUE );
155+ } while (--$ count );
159156
160157 $ output = substr ($ setting , 0 , 12 );
161158 $ output .= $ this ->encode64 ($ hash , 16 );
162159
163160 return $ output ;
164161 }
165162
166- function gensalt_extended ($ input )
167- {
168- $ count_log2 = min ($ this ->iteration_count_log2 + 8 , 24 );
169- # This should be odd to not reveal weak DES keys, and the
170- # maximum valid value is (2**24 - 1) which is odd anyway.
171- $ count = (1 << $ count_log2 ) - 1 ;
172-
173- $ output = '_ ' ;
174- $ output .= $ this ->itoa64 [$ count & 0x3f ];
175- $ output .= $ this ->itoa64 [($ count >> 6 ) & 0x3f ];
176- $ output .= $ this ->itoa64 [($ count >> 12 ) & 0x3f ];
177- $ output .= $ this ->itoa64 [($ count >> 18 ) & 0x3f ];
178-
179- $ output .= $ this ->encode64 ($ input , 3 );
180-
181- return $ output ;
182- }
183-
184163 function gensalt_blowfish ($ input )
185164 {
186165 # This one needs to use a different order of characters and a
@@ -230,20 +209,11 @@ function HashPassword($password)
230209
231210 $ random = '' ;
232211
233- if (CRYPT_BLOWFISH == 1 && !$ this ->portable_hashes ) {
212+ if (CRYPT_BLOWFISH === 1 && !$ this ->portable_hashes ) {
234213 $ random = $ this ->get_random_bytes (16 );
235214 $ hash =
236215 crypt ($ password , $ this ->gensalt_blowfish ($ random ));
237- if (strlen ($ hash ) == 60 )
238- return $ hash ;
239- }
240-
241- if (CRYPT_EXT_DES == 1 && !$ this ->portable_hashes ) {
242- if (strlen ($ random ) < 3 )
243- $ random = $ this ->get_random_bytes (3 );
244- $ hash =
245- crypt ($ password , $ this ->gensalt_extended ($ random ));
246- if (strlen ($ hash ) == 20 )
216+ if (strlen ($ hash ) === 60 )
247217 return $ hash ;
248218 }
249219
@@ -252,7 +222,7 @@ function HashPassword($password)
252222 $ hash =
253223 $ this ->crypt_private ($ password ,
254224 $ this ->gensalt_private ($ random ));
255- if (strlen ($ hash ) == 34 )
225+ if (strlen ($ hash ) === 34 )
256226 return $ hash ;
257227
258228 # Returning '*' on error is safe here, but would _not_ be safe
@@ -268,9 +238,13 @@ function CheckPassword($password, $stored_hash)
268238 }
269239
270240 $ hash = $ this ->crypt_private ($ password , $ stored_hash );
271- if ($ hash [0 ] == '* ' )
241+ if ($ hash [0 ] === '* ' )
272242 $ hash = crypt ($ password , $ stored_hash );
273243
244+ # This is not constant-time. In order to keep the code simple,
245+ # for timing safety we currently rely on the salts being
246+ # unpredictable, which they are at least in the non-fallback
247+ # cases (that is, when we use /dev/urandom and bcrypt).
274248 return $ hash === $ stored_hash ;
275249 }
276- }
250+ }
0 commit comments