password_needs_rehash

(PHP 5 >= 5.5.0, PHP 7, PHP 8)

password_needs_rehash检测散列值是否匹配指定的选项

说明

password_needs_rehash(string $hash, mixed $algo, array $options = ?): bool

此函数检测指定的散列值是否实现了提供的算法和选项。 如果没有,需要重新生成散列值。

参数

hash

一个由 password_hash() 创建的散列值。

algo

一个用来在散列密码时指示算法的密码算法常量

options

一个包含有选项的关联数组。详细的参数说明,请参考文档 密码算法常数

返回值

如果散列需要重新生成才能匹配指定的 algooptions, 则返回 true,否则返回 false

更新日志

版本 说明
7.4.0 现在 algo 参数可以支持 string 类型,但为了向后兼容性,同时支持 int 类型。

范例

示例 #1 password_needs_rehash()用法

<?php

$password 
'rasmuslerdorf';
$hash '$2y$10$YCFsG6elYca568hBi2pZ0.3LDL5wjgxct1N8w/oLR/jfHsiQwCqTS';

// 当硬件性能得到改善时,cost 参数可以再修改
$options = array('cost' => 11);

// 根据明文密码验证储存的散列
if (password_verify($password$hash)) {
    
// 检测是否有更新的可用散列算法
    // 或者 cost 发生变化
    
if (password_needs_rehash($hashPASSWORD_DEFAULT$options)) {
        
// 如果是这样,则创建新散列,替换旧散列
        
$newHash password_hash($passwordPASSWORD_DEFAULT$options);
    }

    
// 使用户登录
}
?>

add a note add a note

User Contributed Notes 4 notes

up
25
php dot net at muer dot nl
9 years ago
nick, this function cannot check if a string is a MD5 or SHA1 hash. It can only tell you if a password, hashed using the password_hash function, needs to be put through the hashing function again to keep up to date with the new defaults.

The only time you can use this function is when your user logs in and you have already checked by means of password_verify that the password entered is actually correct. At that point, if password_needs_rehash returns true, you can put the plain text password through the password_hash function.
up
4
geekasylum at google mail
5 years ago
This function can indeed be used to assist in transparently updating legacy passwords (those not using the password_hash() function - eg: perhaps something using MD5 or SHA1)

In legacy sites, when authenticating a user (during login) first check the password using password_verify(). If that fails it may simply be because the user's password hash was created long ago by a legacy or home-brew password algorithm.

You can then re-check the password against the site's legacy password algorithm.  If that fails too, then the login fails, since the supplied password did not authenticate against either the new, or the old password tests.

If any one of those two test was successfull, you know that the password is good so you would then call password_needs_rehash() on the stored hash, and it will properly indicate if the password hash needs to be re-computed, either because it's an unrecognised (legacy) hash or it's a modern hash created by password_hash(), which may just need its cost index updated.

Simply store the recomputed hash in the database and you now have a password_verify() compatible password for that user and the second test can be skipped in future logins (but still check if it needs rehashing).
up
17
nick at nickstallman dot net
10 years ago
ydroneaud this would be used on a login page, not at any other time.

So if you have a site with MD5 passwords for example, and wish to upgrade to SHA256 for additional security you would put this check in the login script.

This function will take a user's hash and say if it is SHA256, if it isn't then you can take the user's password which you still have as plaintext and rehash it as SHA256.

This lets you gradually update the hashes in your database without disrupting any features or resetting passwords.
up
10
admin at torntech dot com
9 years ago
Some other use-cases for the password_needs_rehash function is when you have specified using the PASSWORD_DEFAULT algorithm for password_hash.
As mentioned on the Password Hashing Predefined Constants and password_hash pages, the algorithm used by PASSWORD_DEFAULT is subject to change as different versions of PHP are released.
Additionally password_needs_rehash would be used if you have changed the optional cost or static salt (DO NOT USE A STATIC SALT) requirements of your password_hash options.

Full example:

<?php

$new
= [
   
'options' => ['cost' => 11],
   
'algo' => PASSWORD_DEFAULT,
   
'hash' => null
];

$password = 'rasmuslerdorf';

//stored hash of password
$oldHash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

//verify stored hash against plain-text password
if (true === password_verify($password, $oldHash)) {
   
//verify legacy password to new password_hash options
   
if (true === password_needs_rehash($oldHash, $new['algo'], $new['options'])) {
       
//rehash/store plain-text password using new hash
       
$newHash = password_hash($password, $new['algo'], $new['options']);
        echo
$newHash;
    }
}
?>

The above example will output something similar to:
$2y$11$Wu5rN3u38.g/XWdUeA6Wj.PD.F0fLXXmZrMNFyzzg2UxkVmxlk41W
To Top