我如何存储我的用户?密码安全吗?
这比普通的 MD5 安全多少?我刚刚开始研究密码安全性。我对 PHP 还很陌生。
$salt = 'csdnfgksdgojnmfnb';
$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
WHERE username = '".mysql_real_escape_string($_POST['username'])."'
AND password = '$password'");
if (mysql_num_rows($result) < 1) {
/* Access denied */
echo "The username or password you entered is incorrect.";
}
else {
$_SESSION['id'] = mysql_result($result, 0, 'id');
#header("Location: ./");
echo "Hello $_SESSION[id]!";
}
How much more safe is this than plain MD5? I've just started looking into password security. I'm pretty new to PHP.
$salt = 'csdnfgksdgojnmfnb';
$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
WHERE username = '".mysql_real_escape_string($_POST['username'])."'
AND password = '$password'");
if (mysql_num_rows($result) < 1) {
/* Access denied */
echo "The username or password you entered is incorrect.";
}
else {
$_SESSION['id'] = mysql_result($result, 0, 'id');
#header("Location: ./");
echo "Hello $_SESSION[id]!";
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
确保密码存储方案安全的最简单方法是使用标准库。
由于安全性往往比大多数程序员单独解决的要复杂得多,而且有更多看不见的搞砸的可能性,因此使用标准库几乎总是最简单和最安全(如果不是唯一)的可用选项。
新的 PHP 密码 API (5.5.0+)
如果您使用 PHP 5.5.0 或更高版本,您可以使用新的简化密码哈希 API
使用 PHP 密码 API 的代码示例:(
如果您仍在使用旧版 5.3.7 或更高版本,您可以安装 ircmaxell/password_compat 来访问内置功能)
< br>
改进加盐哈希:添加胡椒
如果您想要额外的安全性,安全人员现在(2017 年)建议添加 'pepper' 添加到(自动)加盐密码哈希值。
我建议有一个简单的直接类可以安全地实现此模式:
Netsilik/PepperedPasswords
(github)。
它附带 MIT 许可证,因此您可以随心所欲地使用它,即使在专有项目中也是如此。
使用
Netsilik/PepperedPasswords
的代码示例:OLD 标准库
看一下:便携式 PHP 密码哈希框架:phpass 并确保尽可能使用
CRYPT_BLOWFISH
算法。使用 phpass (v0.2) 的代码示例:
PHPass 已在一些非常知名的项目中实现:
好处是你不需要担心细节,这些细节已经由有经验的人编程并审查过被互联网上的很多人所关注。
有关密码存储方案的更多信息,请阅读 Jeff 的博客文章:您可能错误地存储了密码
无论您做什么,如果您选择“我会自己做,谢谢'的方法,不要再使用
MD5
或SHA1
。它们是很好的哈希算法,但出于安全目的被认为已损坏。目前,使用 crypt 和 CRYPT_BLOWFISH 是最佳实践。
PHP 中的 CRYPT_BLOWFISH 是 Bcrypt 哈希的实现。 Bcrypt 基于 Blowfish 分组密码,利用其昂贵的密钥设置来减慢算法速度。
The easiest way to get your password storage scheme secure is by using a standard library.
Because security tends to be a lot more complicated and with more invisible screw up possibilities than most programmers could tackle alone, using a standard library is almost always easiest and most secure (if not the only) available option.
The new PHP password API (5.5.0+)
If you are using PHP version 5.5.0 or newer, you can use the new simplified password hashing API
Example of code using PHP's password API:
(In case you are still using legacy 5.3.7 or newer you can install ircmaxell/password_compat to have access to the build-in functions)
Improving upon salted hashes: add pepper
If you want extra security, the security folks now (2017) recommend adding a 'pepper' to the (automatically) salted password hashes.
There is a simple, drop in class that securely implements this pattern, I recommend:
Netsilik/PepperedPasswords
(github).
It comes with a MIT License, so you can use it however you want, even in proprietary projects.
Example of code using
Netsilik/PepperedPasswords
:The OLD standard library
Take a look at: Portable PHP password hashing framework: phpass and make sure you use the
CRYPT_BLOWFISH
algorithm if at all possible.Example of code using phpass (v0.2):
PHPass has been implemented in some quite well known projects:
The good thing is that you do not need to worry about the details, those details have been programmed by people with experience and reviewed by many folks on the internet.
For more information on password storage schemes, read Jeff`s blog post: You're Probably Storing Passwords Incorrectly
Whatever you do if you go for the 'I'll do it myself, thank you' approach, do not use
MD5
orSHA1
anymore. They are nice hashing algorithm, but considered broken for security purposes.Currently, using crypt, with CRYPT_BLOWFISH is the best practice.
CRYPT_BLOWFISH in PHP is an implementation of the Bcrypt hash. Bcrypt is based on the Blowfish block cipher, making use of it's expensive key setup to slow the algorithm down.
如果您使用参数化查询而不是连接 SQL 语句,您的用户将会更加安全。并且盐对于每个用户来说应该是唯一的,并且应该与密码一起存储哈希。
Your users will be much safer if you used parameterized queries instead of concatenating SQL statements. And the salt should be unique for each user and should be stored along with the password hash.
更好的方法是让每个用户都有一个独特的盐。
使用 salt 的好处是,它使攻击者更难预先生成每个字典单词的 MD5 签名。但是,如果攻击者得知您有固定盐,他们就可以预先生成以您的固定盐为前缀的每个字典单词的 MD5 签名。
更好的方法是每次用户更改密码时,您的系统都会生成随机盐并将该盐与用户记录一起存储。它使得检查密码的成本更高一些(因为您需要在生成 MD5 签名之前查找盐),但它使攻击者更难预先生成 MD5。
A better way would be for each user to have a unique salt.
The benefit of having a salt is that it makes it harder for an attacker to pre-generate the MD5 signature of every dictionary word. But if an attacker learns that you have a fixed salt, they could then pre-generate the MD5 signature of every dictionary word prefixed by your fixed salt.
A better way is each time a user changes their password, your system generate a random salt and store that salt along with the user record. It makes it a bit more expensive to check the password (since you need to look up the salt before you can generate the MD5 signature) but it makes it much more difficult for an attacker to pre-generate MD5's.
随着 PHP 5.5(我所描述的甚至可以用于更早的版本,见下文)即将到来,我建议使用其新的内置解决方案:
password_hash()
和password_verify()
。它提供了几个选项,以达到您需要的密码安全级别(例如通过 $options 数组指定“cost”参数)将返回
正如您可能看到的,该字符串包含 salt以及选项中指定的成本。它还包含所使用的算法。
因此,在检查密码时(例如,当用户登录时),当使用免费的
password_verify()
函数时,它将从密码哈希本身中提取必要的加密参数。如果不指定盐,则每次调用
password_hash()
时生成的密码哈希值都会不同,因为盐是随机生成的。因此,即使密码正确,将先前的哈希值与新生成的哈希值进行比较也会失败。验证的工作原理如下:
我希望提供这些内置函数很快就能在数据被盗的情况下提供更好的密码安全性,因为它减少了程序员在正确实现时需要投入的精力。
有一个小型库(一个 PHP 文件)可以为您提供 PHP 5.3.7+ 中 PHP 5.5 的
password_hash
:https://github.com/ircmaxell/password_compatWith PHP 5.5 (what I describe is available to even earlier versions, see below) around the corner I'd like to suggest to use its new, built-in solution:
password_hash()
andpassword_verify()
. It provides several options in order to achieve the level of password security you need (for example by specifying a "cost" parameter through the$options
array)will return
As you might see, the string contains the salt as well as the cost that was specified in the options. It also contains the algorithm used.
Therefore, when checking the password (for example when the user logs in), when using the complimentary
password_verify()
function it will extract the necessary crypto parameters from the password hash itself.When not specifying a salt, the generated password hash will be different upon every call of
password_hash()
because the salt is generated randomly. Therefore comparing a previous hash with a newly generated one will fail, even for a correct password.Verifying works like this:
I hope that providing these built-in functions will soon provide better password security in case of data theft, as it reduces the amount of thought the programmer has to put into a proper implementation.
There is a small library (one PHP file) that will give you PHP 5.5's
password_hash
in PHP 5.3.7+: https://github.com/ircmaxell/password_compat这对我来说没问题。 Atwood 先生写了MD5 对抗彩虹表的优势,基本上是长盐就像你坐得很漂亮(尽管有一些随机的标点符号/数字,它可以改善它)。
您还可以查看 SHA-1,它最近似乎越来越流行。
That's fine with me. Mr Atwood wrote about the strength of MD5 against rainbow tables, and basically with a long salt like that you're sitting pretty (though some random punctuation/numbers, it could improve it).
You could also look at SHA-1, which seems to be getting more popular these days.
我想补充一下:
为了与旧系统兼容,通常会对密码的最大长度设置限制。这是一个糟糕的安全策略:如果您设置限制,请仅将其设置为密码的最小长度。
为了恢复忘记的密码,您应该发送用户可以更改密码的地址。
密码哈希值可能已过时(算法的参数可能已更新)。通过使用函数
password_needs_rehash()
你可以检查一下。I want to add:
For compatibility with old systems often set a limit for the maximum length of the password. This is a bad security policy: if you set restriction, set it only for the minimum length of passwords.
For recovering a forgotten password you should send the address by which user can change the password.
The password hash may be out of date (parameters of the algorithm may be updated). By using the function
password_needs_rehash()
you can check it out.这是一个 PHP + CouchDB.apache.org 登录系统,不存储明文密码。
根据我读过的建议,它应该是完全安全的。
CMS登录代码: https://github.com/nicerapp/ nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/boot.php#L56
来电
https://github.com/nicerapp/nicerapp/blob/ 24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L171
应用程序特定业务代码:
https://github.com/nicerapp/nicerapp/blob/ 24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/ajax_login.php#L87
来电
https://github.com/nicerapp/nicerapp/blob/ 24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L230
这又调用:
https://github。 com/nicerapp/nicerapp/blob/2d479b3e22dce9e7073525481b775f1bf7389634/nicerapp/apps/nicer.app/webmail/recrypt.php#L2
并将网络邮件应用程序配置数据编辑到数据库中:
https://github.com/ Nicerapp/nicerapp/blob/main/nicerapp/apps/nicer.app/webmail/ajax_editConfig.php
Here's a PHP + CouchDB.apache.org login system that doesn't store plaintext passwords.
According to the advice that I've read, it should be totally secure.
CMS login code : https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/boot.php#L56
calls
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L171
app(s) specific business code :
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/ajax_login.php#L87
calls
https://github.com/nicerapp/nicerapp/blob/24ff0ca317b28c1d91aee66041320976a6d76da7/nicerapp/functions.php#L230
which in turn calls :
https://github.com/nicerapp/nicerapp/blob/2d479b3e22dce9e7073525481b775f1bf7389634/nicerapp/apps/nicer.app/webmail/recrypt.php#L2
and to edit the webmail app config data into the database :
https://github.com/nicerapp/nicerapp/blob/main/nicerapp/apps/nicer.app/webmail/ajax_editConfig.php