@@ -159,33 +159,29 @@ public function changeEmail($new_email) {
159159 }
160160
161161 public function changePassword ($ new_password ) {
162- $ password_hash = null ; $ password_salt = null ;
163- self ::createPassword ($ new_password , $ password_hash , $ password_salt );
162+ $ password_hash = self ::createPassword ($ new_password );
164163 if (!isset (Common::$ database )) {
165164 Common::$ database = DatabaseDriver::getDatabaseObject ();
166165 }
167166 $ successful = false ;
168167 try {
169- $ stmt = Common::$ database ->prepare ("
168+ $ stmt = Common::$ database ->prepare ('
170169 UPDATE `users` SET
171- `password_hash` = :password_hash,
172- `password_salt` = :password_salt
170+ `password_hash` = :password_hash, `password_salt` = NULL
173171 WHERE `id` = :user_id;
174- " );
172+ ' );
175173 $ stmt ->bindParam (":user_id " , $ this ->id , PDO ::PARAM_INT );
176174 $ stmt ->bindParam (":password_hash " , $ password_hash , PDO ::PARAM_STR );
177- $ stmt ->bindParam (":password_salt " , $ password_salt , PDO ::PARAM_STR );
178175 $ successful = $ stmt ->execute ();
179176 $ stmt ->closeCursor ();
180177 if ($ successful ) {
181178 $ this ->password_hash = (string ) $ password_hash ;
182- $ this ->password_salt = (string ) $ password_salt ;
183179 $ key = "bnetdocs-user- " . $ this ->id ;
184180 $ obj = Common::$ cache ->get ($ key );
185181 if ($ obj !== false ) {
186182 $ obj = unserialize ($ obj );
187183 $ obj ->password_hash = $ this ->password_hash ;
188- $ obj ->password_salt = $ this -> password_salt ;
184+ $ obj ->password_salt = null ;
189185 $ obj = serialize ($ obj );
190186 Common::$ cache ->set ($ key , $ obj , 300 );
191187 }
@@ -229,13 +225,31 @@ public function changeUsername($new_username) {
229225 }
230226
231227 public function checkPassword ($ password ) {
232- if (is_null ($ this ->password_hash )
233- || is_null ( $ this -> password_salt ))
228+ if (is_null ($ this ->password_hash )) {
229+ // no password set
234230 return false ;
235- $ pepper = Common::$ config ->bnetdocs ->user_password_pepper ;
236- $ salt = $ this ->password_salt ;
237- $ hash = strtoupper (hash ("sha256 " , $ password .$ salt .$ pepper ));
238- return ($ hash === strtoupper ($ this ->password_hash ));
231+ }
232+
233+ if (substr ($ this ->password_hash , 0 , 1 ) == '$ ' ) {
234+ // new style bcrypt password
235+
236+ $ cost = Common::$ config ->bnetdocs ->user_password_bcrypt_cost ;
237+ $ match = password_verify ($ password , $ this ->password_hash );
238+ $ rehash = password_needs_rehash (
239+ $ this ->password_hash , PASSWORD_BCRYPT , array ('cost ' => $ cost )
240+ );
241+
242+ return ($ match && !$ rehash ); // will deny if not match or needs rehash
243+
244+ } else {
245+ // old style sha256 password
246+
247+ $ pepper = Common::$ config ->bnetdocs ->user_password_pepper ;
248+ $ salt = $ this ->password_salt ;
249+ $ hash = strtoupper (hash ('sha256 ' , $ password .$ salt .$ pepper ));
250+
251+ return ($ hash === strtoupper ($ this ->password_hash ));
252+ }
239253 }
240254
241255 public static function create (
@@ -244,8 +258,7 @@ public static function create(
244258 if (!isset (Common::$ database )) {
245259 Common::$ database = DatabaseDriver::getDatabaseObject ();
246260 }
247- $ password_hash = null ; $ password_salt = null ;
248- self ::createPassword ($ password , $ password_hash , $ password_salt );
261+ $ password_hash = self ::createPassword ($ password );
249262 $ successful = false ;
250263 try {
251264 $ stmt = Common::$ database ->prepare ("
@@ -255,15 +268,13 @@ public static function create(
255268 `options_bitmask`, `timezone`
256269 ) VALUES (
257270 NULL, :email, :username, :display_name, NOW(),
258- NULL, :password_hash, :password_salt,
259- :options_bitmask, NULL
271+ NULL, :password_hash, NULL, :options_bitmask, NULL
260272 );
261273 " );
262274 $ stmt ->bindParam (":email " , $ email , PDO ::PARAM_STR );
263275 $ stmt ->bindParam (":username " , $ username , PDO ::PARAM_STR );
264276 $ stmt ->bindParam (":display_name " , $ display_name , PDO ::PARAM_STR );
265277 $ stmt ->bindParam (":password_hash " , $ password_hash , PDO ::PARAM_STR );
266- $ stmt ->bindParam (":password_salt " , $ password_salt , PDO ::PARAM_STR );
267278 $ stmt ->bindParam (":options_bitmask " , $ options_bitmask , PDO ::PARAM_INT );
268279 $ successful = $ stmt ->execute ();
269280 $ stmt ->closeCursor ();
@@ -276,15 +287,9 @@ public static function create(
276287 }
277288 }
278289
279- public static function createPassword ($ password , &$ hash , &$ salt ) {
280- $ pepper = Common::$ config ->bnetdocs ->user_password_pepper ;
281-
282- $ gmp = gmp_init (time ());
283- $ gmp = gmp_mul ($ gmp , mt_rand ());
284- $ gmp = gmp_mul ($ gmp , gmp_random_bits (64 ));
285- $ salt = strtoupper (gmp_strval ($ gmp , 36 ));
286-
287- $ hash = strtoupper (hash ("sha256 " , $ password .$ salt .$ pepper ));
290+ public static function createPassword ($ password ) {
291+ $ cost = Common::$ config ->bnetdocs ->user_password_bcrypt_cost ;
292+ return password_hash ($ password , PASSWORD_BCRYPT , array ('cost ' => $ cost ));
288293 }
289294
290295 public static function findIdByEmail ($ email ) {
0 commit comments