我有一个人们可以注册的网站,我需要加密他们的密码。我研究了它,但我发现任何方法都不会受到现代GPU的强大影响。
所以我来到StackOverflow的好人那里问,最强的加密方法是什么,我尽力阻止人们掌握数据库,但我希望尽可能确保他们的如果数据库以某种方式被盗,数据将没有问题。
我想知道的其他事情是,以某种方式随机化密码中的字符会更安全,但是你可以将它们再次随机化以便登录吗?
修改 我使用了Andrew Moore(How do you use bcrypt for hashing passwords in PHP?)的bcrypt实现并提出了这个:
public static function Encrypt($Str,$Salt)
{
$bcrypt = new \bcrypt();
return $bcrypt->hash(SERVER_SALT . md5($Str) . $Salt);
}
如果有人发现任何错误或任何弱点,请告诉我。
答案 0 :(得分:17)
对于密码,您无法击败bcrypt
。以下是SO上的链接:How do you use bcrypt for hashing passwords in PHP?。它的主要优点是:固有的慢(以及安全)。虽然普通用户将使用一次,并且不会理解十分之一到一百万分之一秒之间的差异,但是一个破解者会发现,他现在需要<而不是在四天内找到密码em> 12个世纪(除了强迫Blowfish每秒一百万次尝试不需要四天:除非实施错误和无法预见的加密突破,the heat death of the Universe will still come first)。
对于数据,我依赖数据库引擎本身; MySQL支持AES,这非常好。是的,有足够的GPU可以击败它,并且由于在本世纪内破解代码需要大约四十亿,他可能也会得到很好的数量折扣。但我不担心。
关于&#34;随机化&#34;密码,它没有任何意义。如果有人要求强制使用您的密码,他将有相同的概率找到随机序列或非随机序列。如果使用字典攻击(即,不尝试从AAAAA到ZZZZZ的所有内容,但尝试ABRAHAM,ACCORDION,......,比如ZYGOTE)可能会有所帮助。但即使这样,对服务器的攻击也不会改变任何东西(服务器收到非随机密码!),并且 salting 会更好地抵消对存储的哈希的攻击,{{1} }自动执行:即存储$ 76XJ的散列:MICKEYMOUSE而不是MICKEYMOUSE的散列,以及处理额外$ 76XJ所需的开销:&#39;在输入上。虽然随机化必须修复,但是76X.J:&#39;序列在每次写入时都是完全不同的 - 祝你好运
如果你自己实施盐腌(如上图所示,你不需要bcrypt
),你可以通过生成一个独特的随机序列并将其存储在密码字段或第二场。例如
bcrypt
然后,在收到Alice(&#34; mickeymouse&#34;)的密码后,您将查看数据库以查看是否存在名为user password
alice d9c06f88:6c14d6d313d7cbcb132b5c63650682c4
的用户。如果是,请恢复盐(此处为alice
)和哈希值。如果没有,请设置&#34; BAD&#34;标记并获取固定的盐和哈希值(例如d9c06f88
)。
在MySQL中,这可以使用UNION来完成:
12345678:0000000...
将在大致相同的时间内检索正确的数据或不正确的集合(这可以防止有人猜测存在哪些名称,而不是通过计算回答所需的时间而错误的用户或密码&#34;)
然后连接salt和密码,并生成SELECT password_fields FROM users WHERE user=? AND hash=?
UNION SELECT
'12345789' as salt,
'ffffffffffffffffffffffff' as hash,
'fake' as user
LIMIT 1;
的哈希值。如果不匹配,或&#34; BAD&#34;如果设置了flag,则拒绝密码(而不是使用&#39; bad&#39;标志,您可以重复测试MySQL已经执行过的用户匹配:您可以通过将最后一个字符替换为无效字符来初始化用户名,以确保它永远不会与真实用户匹配。)
选择一个固定字符串的附加信息是有用的,因为你想要三种情况,&#34;用户不存在&#34;,&#34;用户存在但密码不正确&#34;和&#34;用户存在,密码正确&#34;尽可能相似(复杂程度相同,计算费用相同)。
这样,攻击者就不太可能分辨出发生了什么:用户是不正确的?密码错了吗?等等。如果时间足够不同(比如对有效用户进行两次查询,对无效用户进行一次查询),小心,时间和好秒表的攻击者可以统计确定是否存在给定用户名。
对于用户,即使名称比较也是
d9c06f88:mickeymouse
所以告诉HTTP(s)连接的另一端发生的事情并不容易。
出于同样的原因,您将不为&#34; Bad user&#34;返回两个不同的错误和#34;密码错误&#34;,但总是&#34;糟糕的用户或密码&#34 ;;对于用户,可以选择接收到他/她的注册电子邮件的电子邮件以提醒他/她用户名。当然,您希望系统不在发送类似电子邮件到同一用户24小时之前发送此类电子邮件,以防止系统被利用来骚扰虚假的人# 34;恢复电子邮件&#34;。
如果您执行发送电子邮件,您将等到预设时间过期(例如,3秒),然后通知用户 用户名是否存在,然后他们应该检查他们的收件箱(和垃圾邮件文件夹以获得良好的衡量标准)。
提高服务器安全性以防止强制攻击的一种便捷方法是在密码身份验证上实现延迟,并且可能(如果您真的很偏执)在经过一些X次错误尝试后进行了CAPTCHA锁定
您不想首次尝试CAPTCHA,因为用户对CAPTCHA的看法很暗淡。
延迟锁定通常使用 johnsmith against johnsmith if johnsmith exists
johnsmith against johnsmit? if johnsmith does not exist
(或等效的)实施,或使用&#34;锁定,直到管理员手动重置为止。战略。 两种方法都不好。锁定功能可用于通过锁定用户或创建大量服务器线程来创建拒绝服务攻击,密码认证延迟&#34;状态(他们不会使用CPU,但他们仍然使用内存,套接字和其他资源)。
在某些情况下,这可能会在不知不觉中发生。似乎有一些白痴使用我的银行,每隔几个月我就会收到一条短信说#34;错误的密码输入你的家庭银行系统&#34;。然后我必须从我的手机登录,重置不成功的尝试计数器;因为如果白痴没有意识到他无法进入他的帐户,因为他输入我的帐号,已经三次,那就是我的帐户被锁定,我必须亲自前往银行并请求他们重置我的访问权限。我告诉你,这是幽冥地区的主要痛苦,即使知道它不是他们的错,我仍然怨恨我的银行。你不想在你的用户中产生这样的感受。
最好减轻客户的负担:
sleep
答案 1 :(得分:0)
AES 256位加密非常“强大”,这意味着它是最新的加密标准之一,难以破解。我已经读过,如果你采用蛮力方法来破解它,你将需要世界上所有的计算能力。
退房:
How to do AES256 decryption in PHP?
和
http://en.wikipedia.org/wiki/Advanced_Encryption_Standard http://www.andrew-kirkpatrick.com/2013/01/aes-encryption-with-php-256-bit-using-iv/
希望有所帮助。