PHP Strongest one way encryption/hashing method
我有一个网站,人们可以注册,我需要加密他们的密码。我已经研究过了,但是我找不到任何方法可以不被现代GPU的力量打败。
所以我来问StackOverflow的好人,什么是最强大的加密方法,我已经尽了最大的努力阻止人们接触数据库,但我想尽可能确保如果数据库被偷了,他们的数据会很好。
我想知道的其他事情是,将密码中的字符随机化会更安全吗?但在某种程度上,您可以再次随机化它们以便登录?
编辑:我使用了Andrew Moore的Bcrypt实现(如何使用Bcrypt在PHP中散列密码?)然后想出这个:
1 2 3 4 5 |
如果有人发现它有任何问题或弱点,请告诉我。
对于密码,您不能打败
对于数据,我将依赖数据库引擎本身;MySQL支持AES,这很好。是的,有了足够的GPU,一个人就可以打败它,而且由于要在本世纪内破解代码,一个人需要大约40亿个GPU,他可能也会得到很好的数量折扣。但我不担心。好的。
至于密码的"随机化",它将毫无用处。如果有人想用暴力破解你的密码,他同样有可能找到随机序列或非随机序列。如果一个人使用字典攻击(也就是说,不是尝试从aaaa到zzz的所有东西,而是尝试亚伯拉罕,手风琴,……)可能会有所帮助。直到,比如,合子)。但是即使这样,对服务器的攻击也不会改变任何东西(服务器接收到非随机密码!)对存储的哈希的攻击最好通过salting来消除,这是
如果您自己实现了salting(如上所示,使用EDOCX1[0]您不需要),您可以通过生成一个唯一的随机序列并将其存储在密码字段或第二个字段中来实现。例如好的。
1 2 | user password alice d9c06f88:6c14d6d313d7cbcb132b5c63650682c4 |
然后,在Alice("MickeyMouse")收到密码后,您将在数据库中查看是否存在名为
在mysql中,可以使用union来完成:好的。
1 2 3 4 5 6 |
将在大致相同的时间内检索正确的数据或不正确的集合(这可以防止有人猜测哪些名称存在,哪些名称不存在,通过计时回答"错误的用户或密码"所需的时间)。好的。
然后连接salt和密码,生成EDOCX1的散列值(0)。如果不匹配,或者设置了"bad"标志,则拒绝密码(而不是使用"bad"标志,您可以重复MySQL已经进行的用户匹配测试:您可以通过将最后一个字符替换为无效字符来初始化用户名,以确保它永远不会匹配真正的用户)。好的。非信息安全
选择固定字符串的附加扭曲非常有用,因为您希望"用户不存在"、"用户存在但密码不正确"和"用户存在且密码正确"这三种情况尽可能相似(复杂性相同,计算费用相同)。好的。
这样,攻击者就不太可能知道发生了什么:用户是否不正确?密码错误吗?等等。如果时间足够不同(比如对有效用户进行两次查询,对无效用户进行一次查询),则具有谨慎、时间和良好秒表的攻击者可以统计确定给定用户名是否存在。好的。
对于用户,即使名称比较好的。
1 2 | johnsmith against johnsmith if johnsmith exists johnsmith against johnsmit? if johnsmith does not exist |
因此,说出从HTTP连接的另一端发生的事情并不容易。好的。
出于同样的原因,对于"坏用户"和"坏密码",您不会返回两个不同的错误,而是始终返回一个"坏用户或密码";对于用户,可以选择接收一封发送到他/她的注册电子邮件的电子邮件,以提醒他/她用户名。当然,你希望系统在24小时内不发送类似的电子邮件给同一个用户,以防止系统被利用来用虚假的"恢复电子邮件"骚扰某人。好的。
如果您确实发送了电子邮件,您将等待到预设时间到期(例如,3秒),然后通知用户如果用户名存在,那么他们应该检查其收件箱(以及垃圾邮件文件夹以获得良好的度量)。好的。有一段时间会有这样的密码
提高服务器安全性的一个方便方法是在密码验证上实现延迟,并且(如果您真的很偏执的话)在尝试了X次错误的尝试之后,可能会进行验证码锁定。好的。
您不想在第一次尝试时验证,因为用户对验证码的看法很模糊。好的。
延迟锁定通常使用
在某些情况下,这可能是无意中发生的。似乎有个白痴在使用我的银行,每隔几个月我就会收到一条短信,上面写着"在你的家庭银行系统中输入了错误的密码"。然后我必须从我的手机登录,重置失败的尝试计数器;因为如果白痴没有意识到他不能进入他的帐户,因为他输入了我的帐号,三次,这是我的帐户被锁定,我必须亲自去银行,求他们重置我的访问权限。让我告诉你,这是下一个地区的一大痛苦,即使知道这不是他们的错,我仍然怨恨我的银行。你不想在你的用户中产生这样的感觉。好的。
最好是减轻客户的负担:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | (very pseudo code) login = FAIL if in SECURITY LOCKOUT MODE for this account if a session is open and contains a last-attempt time if at least DELAY seconds have elapsed since last-attempt check the password if it is correct login = OK zero password counter, exit lockout mode. # An"innocent" user enters with no lockout! Yay! end else #"Early knocker". Either a bruteforcing robot # or a too clever user in a hurry. But we can't # tell them apart. end else # No session. Either a sessionless bruteforcing robot # or a unaware, innocent user. Again we can't tell them # apart. So we bounce both. # But a genuine user will assume he has mistyped the password, # or anyway will read the warning page, and will login after ONE # round of delay. # Users with password saved in browser will just click #"login" again and be logged in. # A robot will find itself delayed and ALL ITS PASSWORDS IGNORED # every single time. Even if it finds the right password... it will # not work. end else check the password if it is correct # Good user, first attempt, fast login. login = OK else # Beginning to doubt this is a good user... increase password counter if it is > MAX_ATTEMPTS enter SECURITY LOCKOUT MODE for this account end end end if login is not OK generate a page with HTTP_REFRESH time of DELAY+1 seconds and a session ID, saying"User or password unknown, or you tried to login before HH:MM:SS (DELAY seconds). The page might also contain a Javascript timer, just in case. The delay is 1s more than necessary as a safety margin. end |
好啊。
AES256位加密非常"强大",这意味着它是最新的加密标准之一,很难破解。我读到过,如果你用暴力破解它,你将需要世界上所有的计算能力。
退房:
如何在PHP中进行AES256解密?
还有:
http://en.wikipedia.org/wiki/advanced_encryption_标准http://www.andrew-kirkpatrick.com/2013/01/aes-encryption-with-php-256-bit-using-iv/
希望有帮助。