如何在 PHP 中使用 Blowfish 创建和存储密码哈希值

发布于 2024-10-17 16:44:54 字数 549 浏览 12 评论 0原文

1) 如何使用 crypt() 创建安全的 Blowfish 密码哈希值?

$hash = crypt('somePassword', '$2a$07$nGYCCmhrzjrgdcxjH$');

1a) “$2a”的意义是什么?这是否只是表明应该使用 Blowfish 算法?
1b) “$07”的意义是什么?值越高是否意味着哈希值越安全?
1c) “$nGYCCmhrzjrgdcxjH$”的意义是什么?这是要使用的盐吗?这应该是随机生成的吗?硬编码?

2) 如何存储 Blowfish 哈希值?

echo $hash;
//Output: $2a$07$nGYCCmhrzjrgdcxjH$$$$.xLJMTJxaRa12DnhpAJmKQw.NXXZHgyq

2a) 其中哪一部分应存储在数据库中?
2b) 列 (MySQL) 应使用什么数据类型?

3) 应如何验证登录尝试?

1) How do you create secure Blowfish hashes of passwords with crypt()?

$hash = crypt('somePassword', '$2a$07$nGYCCmhrzjrgdcxjH

1a) What is the significance of "$2a"? Does it just indicate that the Blowfish algorithm should be used?
1b) What is the significance of "$07"? Does a higher value imply a more secure hash?
1c) What is the significance of "$nGYCCmhrzjrgdcxjH$"? Is this the salt that will be used? Should this be randomly generated? Hard-coded?

2) How do you store Blowfish hashes?

echo $hash;
//Output: $2a$07$nGYCCmhrzjrgdcxjH$$.xLJMTJxaRa12DnhpAJmKQw.NXXZHgyq

2a) What part of this should be stored in the database?
2b) What data type should be used for the column (MySQL)?

3) How should one verify a login attempt?

);

1a) What is the significance of "$2a"? Does it just indicate that the Blowfish algorithm should be used?
1b) What is the significance of "$07"? Does a higher value imply a more secure hash?
1c) What is the significance of "$nGYCCmhrzjrgdcxjH$"? Is this the salt that will be used? Should this be randomly generated? Hard-coded?

2) How do you store Blowfish hashes?

2a) What part of this should be stored in the database?
2b) What data type should be used for the column (MySQL)?

3) How should one verify a login attempt?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌吟 2024-10-24 16:44:54

您应该存储 crypt 的整个输出,将其拆分没有太多意义,因为无论如何您都需要为要散列的每个密码生成一个新的盐。正如马特提到的那样,使用固定的隐藏盐是错误的——每个哈希的盐应该不同。

有关详细信息,请参阅 http://www.openwall.com/articles/PHP-Users-Passwords - 我建议使用 phpass 库,因为它可以为您生成随机盐,这与 crypt() 不同。

You should store the entire output of crypt, there's not a lot of point in splitting it up, because you need to generate a new salt for each password you're hashing in any case. Using a fixed hidden salt as mentioned by Matt is wrong - the salt should be different for every hash.

For more information see http://www.openwall.com/articles/PHP-Users-Passwords - I recommend using the phpass library because it handles generating a random salt for you, unlike crypt().

许仙没带伞 2024-10-24 16:44:54

1a) 加密强度 - 要求在 4..31 范围内。请参阅http://php.net/manual/en/function.crypt.php

1b) 参见 1a

1c) 参见 1a。 “salt”不应该是随机的,否则您将无法为给定的输入重新生成相同的哈希值 - 请参阅 3.

2a) 严格来说,除了哈希值之外的所有内容(以防数据库遭到破坏)。另外,将盐存储在 Web 服务器文档根目录下无法访问的文件中,并将其包含在内。尽可能设置最严格的权限;理想情况下,只读 Web 主机服务(例如 apache),没有写入或执行权限。不太严格地说,取决于您希望对黑客采取何种防御措施。不储存盐只会让生活变得更加困难;他们仍然必须将数据正确输入到算法中 - 但为什么要让它变得更容易呢?

2b) VARCHAR(32) 应该适合河豚,如果不存储哈希值

3) 假设您已经运行了正确的注入预防代码等。所以请不要盲目复制下面的内容 (最好使用 PDO 而不是 mysql 扩展)。以下特定于河豚、SHA-256 和 SHA-512,它们都返回哈希中的盐。需要修改其他算法...

//store this in another file outside web directory and include it
$salt = '$2a$07$somevalidbutrandomchars


...

//combine username + password to give algorithm more chars to work with
$password_hash = crypt($valid_username . $valid_password, $salt)

//Anything less than 13 chars is a failure (see manual)
if (strlen($password_hash) < 13 || $password_hash == $salt)
then die('Invalid blowfish result');

//Drop the salt from beginning of the hash result. 
//Note, irrespective of number of chars provided, algorithm will always 
//use the number defined in constant CRYPT_SALT_LENGTH
$trimmed_password_hash = substring($password_hash, CRYPT_SALT_LENGTH);
mysql_query("INSERT INTO `users` (username,p assword_hash) VALUES '$valid_username', '$trimmed_password_hash'");

...

$dbRes = mysql_query("SELECT password_hash FROM `users` WHERE username = '$user_input_username' LIMIT 1");
//re-apply salt to output of database and re-run algorithm testing for match
if (substring($salt, CRYPT_SALT_LENGTH) . mysql_result($dbRes, 0, 'password_hash') ) ===
        crypt($user_input_username . $user_input_password, $salt) ) {
    //... do stuff for validated user
}

1a) Strength of encryption - requirement in the range of 4..31. See http://php.net/manual/en/function.crypt.php

1b) See 1a

1c) See 1a. 'salt' should not be random, or you would not be able to regenerate the same hash for a given input - see 3.

2a) Strictly speaking, everything except the hash (in case database is compromised). Also, store your salt in a file not accessible beneath the web server's document root and include it. Set it with the strictest permissions possible; ideally read only to web host service (e.g. apache), no write or execute privileges. Less strictly speaking, depends how defensive you wish to be against hackers. Not storing the salt just makes life more difficult; they still have to get the data being input to the algorithm right - but why make it easier?

2b) VARCHAR(32) should be fine for blowfish, if not storing the hash

3) Assuming you've already run the proper injection prevention code, etc.. so please don't just copy the below blindly (and ideally use PDO instead of mysql extension). The below is specific to blowfish, SHA-256 and SHA-512 which all return the salt within the hash. Would need modification for other algorithms...

//store this in another file outside web directory and include it
$salt = '$2a$07$somevalidbutrandomchars


...

//combine username + password to give algorithm more chars to work with
$password_hash = crypt($valid_username . $valid_password, $salt)

//Anything less than 13 chars is a failure (see manual)
if (strlen($password_hash) < 13 || $password_hash == $salt)
then die('Invalid blowfish result');

//Drop the salt from beginning of the hash result. 
//Note, irrespective of number of chars provided, algorithm will always 
//use the number defined in constant CRYPT_SALT_LENGTH
$trimmed_password_hash = substring($password_hash, CRYPT_SALT_LENGTH);
mysql_query("INSERT INTO `users` (username,p assword_hash) VALUES '$valid_username', '$trimmed_password_hash'");

...

$dbRes = mysql_query("SELECT password_hash FROM `users` WHERE username = '$user_input_username' LIMIT 1");
//re-apply salt to output of database and re-run algorithm testing for match
if (substring($salt, CRYPT_SALT_LENGTH) . mysql_result($dbRes, 0, 'password_hash') ) ===
        crypt($user_input_username . $user_input_password, $salt) ) {
    //... do stuff for validated user
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文