Shu*_*ker 4 php password-storage
我在很多文章中都读过,我们应该在散列之前将一个独特的盐与每个密码结合起来并将盐存储在数据库中进行验证,但如何将密码本身用作盐?
这样做会有好处,因为盐对于每个盐都是唯一的,并且它将被隐藏,因为它将被存储在任何地方.
我上面给出的一个简单例子是:
$hashToStore=sha1(strrev($password).$password);
Run Code Online (Sandbox Code Playgroud)
上面我只是颠倒密码并将其用作盐(我将做更复杂的事情,然后在开发中将其反转.)
这是存储密码的更好方法,还是一种不好的做法.
PS:我完全了解php最新的内置功能, crypt()并在现实世界中使用它,但还想要上面的评论.
一个常见的错误是在每个哈希中使用相同的salt.盐被硬编码到程序中,或者随机生成一次.这是无效的,因为如果两个用户拥有相同的密码,他们仍然会有相同的哈希值.攻击者仍然可以使用反向查找表攻击同时对每个哈希运行字典攻击.他们只需要在每次密码猜测之前将盐应用于哈希值.如果将盐硬编码为流行产品,则可以为该盐构建查找表和彩虹表,以便更容易破解产品产生的哈希值.
每次用户创建帐户或更改密码时,都必须生成新的随机盐.
[...]很容易被带走并尝试组合不同的哈希函数,希望结果更安全.但实际上,这样做的好处很少.它所做的只是创建互操作性问题,有时甚至可能使哈希不太安全.永远不要试图发明自己的加密,始终使用专家设计的标准.有人会争辩说使用多个散列函数会使计算散列的过程变慢,因此破解速度较慢,但是有一种更好的方法可以使破解过程变慢,我们稍后会看到.
以下是我在互联网论坛上看到的糟糕古怪哈希函数的一些例子.
Run Code Online (Sandbox Code Playgroud)md5(sha1(password)) md5(md5(salt) + md5(password)) sha1(sha1(password)) sha1(str_rot13(password + salt)) md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))不要使用任何这些.
应使用密码安全伪随机数发生器(CSPRNG)生成盐.CSPRNG与普通的伪随机数生成器非常不同,比如"C"语言的rand()函数.顾名思义,CSPRNG设计为加密安全,这意味着它们提供高水平的随机性并且完全不可预测.我们不希望我们的盐是可预测的,因此我们必须使用CSPRNG.下表列出了一些流行编程平台的一些CSPRNG.(PHP:mcrypt_create_iv,openssl_random_pseudo_bytes)
salt需要是每用户每个密码唯一的.每次用户创建帐户或更改密码时,都应使用新的随机盐对密码进行哈希处理.切勿重复使用盐.盐也需要很长,因此有许多可能的盐.根据经验,使你的盐至少与哈希函数的输出一样长.salt应该与哈希一起存储在用户帐户表中.
存储密码
- 使用CSPRNG生成长的随机盐.
- 将salt添加到密码中,并使用标准加密哈希函数(如SHA256)对其进行哈希处理.
- 将salt和hash都保存在用户的数据库记录中.
验证密码
- 从数据库中检索用户的salt和hash.
- 将salt添加到给定密码并使用相同的哈希函数对其进行哈希处理.
- 将给定密码的哈希值与数据库中的哈希值进行比较.如果匹配,则密码正确.否则,密码不正确.
在本页的底部,有PHP,C#,Java和Ruby中的salted密码哈希实现.
在Web应用程序中,始终在服务器上进行哈希处理
如果您正在编写Web应用程序,您可能想知道在哪里哈希.是否应该使用JavaScript在用户的浏览器中对密码进行哈希处理,还是应该"明确地"将密码发送到服务器并在那里进行哈希处理?
即使您在JavaScript中散列用户的密码,您仍然需要在服务器上散列哈希值.考虑一个网站,该网站在用户的浏览器中散列用户密码,而不会在服务器上散列哈希值.要对用户进行身份验证,此网站将接受来自浏览器的哈希,并检查该哈希是否与数据库中的哈希完全匹配.这似乎比在服务器上进行散列更安全,因为用户的密码永远不会发送到服务器,但事实并非如此.
问题是客户端哈希在逻辑上成为用户的密码.用户需要进行身份验证的全部操作是告诉服务器密码的哈希值.如果坏人得到了用户的哈希,他们可以使用它来验证服务器,而不知道用户的密码!因此,如果坏人以某种方式窃取了这个假设网站的哈希数据库,他们就可以立即访问每个人的帐户而无需猜测任何密码.
这并不是说你不应该在浏览器中哈希,但是如果你这样做,你也必须在服务器上哈希.浏览器中的哈希当然是个好主意,但请考虑以下几点来实现:
客户端密码哈希不能替代HTTPS(SSL/TLS).如果浏览器和服务器之间的连接不安全,则中间人可以在下载时修改JavaScript代码以删除散列功能并获取用户密码.
某些Web浏览器不支持JavaScript,有些用户在浏览器中禁用JavaScript.因此,为了获得最大的兼容性,您的应用程序应检测浏览器是否支持JavaScript并在服务器上模拟客户端哈希(如果不支持).
你也需要为客户端哈希加盐.显而易见的解决方案是使客户端脚本向服务器询问用户的salt.不要这样做,因为它让坏人在不知道密码的情况下检查用户名是否有效.由于您在服务器上进行散列和盐析(使用良好的盐),因此可以使用与特定于站点的字符串(例如域名)连接的用户名(或电子邮件)作为客户端盐.
来源:https://crackstation.net/hashing-security.htm
所以,回答你的问题,坏主意,非常糟糕的主意.