如何衡量密码的强度?
我一直在寻找一种有效的算法,可以让我准确地了解密码的强度。
我发现几个不同的网站使用几种不同的算法,因为我在不同的网站上获得不同的密码强度评级。
I was looking for an effective algorithm that can give me an accurate idea of how strong a password is.
I found that several different websites use several different algorithms as I get different password strength ratings on different websites.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这已经成为我在 PHP/MySQL 中使用密码的最佳实践的大脑转储。
这里提出的想法通常不是我自己的,而是我迄今为止发现的最好的想法。
Ensure you are using SSL for all operations involving user information. All pages that involve these forms should check they are being called via HTTPS, and refuse to work otherwise.
您只需限制允许的失败登录次数即可消除大多数攻击。
允许使用相对较弱的密码,但存储每个用户登录失败的次数,如果超过该次数,则需要通过电子邮件进行验证码或密码验证。我将最大失败次数设置为 5。
需要仔细考虑向用户呈现登录失败,以免向攻击者提供信息。
由于用户不存在而导致的登录失败应返回与由于密码错误而导致的登录失败相同的消息。提供不同的消息将使攻击者能够确定有效的用户登录。
另外,请确保在使用有效密码进行过多登录失败以及使用错误密码进行过多登录失败时返回完全相同的消息。提供不同的消息将使攻击者能够确定有效的用户密码。相当多的用户在被迫重置密码时只会将其恢复为原来的状态。
遗憾的是,限制每个 IP 地址允许的登录数量并不实际。一些提供商(例如 AOL)和大多数公司代理他们的网络请求。实施此限制将有效消除这些用户。
I've found checking for dictionary words before submit to be inefficient as either you have to send a dictionary to the client in javascript, or send an ajax request per field change. I did this for a while and it worked ok, but didn't like the traffic it generated.
检查固有的弱密码减去字典单词是实用的客户端,使用一些简单的 JavaScript。
提交后,我检查字典单词和包含密码的用户名,反之亦然服务器端。非常好的词典很容易下载,并且对它们的测试也很简单。这里的一个问题是,要测试字典单词,您需要向数据库发送查询,该数据库再次包含密码。我解决这个问题的方法是预先使用简单的加密和末端定位的 SALT 来加密我的字典,然后测试加密的密码。并不理想,但比纯文本更好,并且仅在物理计算机和子网上的人员的网络上。
一旦您对他们选择的密码感到满意,请先使用 PHP 对其进行加密,然后进行存储。下面的密码加密功能也不是我的想法,但是解决了很多问题。 PHP 内的加密可防止共享服务器上的人员拦截您未加密的密码。为每个用户添加一些不会改变的内容(我使用电子邮件,因为这是我网站的用户名)并添加哈希值(SALT 是我为每个网站更改的短常量字符串)可以增加对攻击的抵抗力。由于 SALT 位于密码内,并且密码可以是任意长度,因此使用彩虹表攻击几乎不可能。
或者,这也意味着人们无法更改他们的电子邮件,并且您也无法在不使每个人的密码无效的情况下更改 SALT。
编辑:我现在建议使用 PhPass 而不是我在这里滚动你自己的函数,或者只是忘记用户登录完全并使用 OpenID 代替。
我的 Jqueryish 客户端密码表。目标应该是一个div。它的宽度将在 0 到 100 之间变化,背景颜色将根据脚本中表示的类而变化。再次大部分是从我发现的其他东西中偷来的:
This has grown to my general brain dump of best practices for working with passwords in PHP/MySQL.
The ideas presented here are generally not my own, but the best of what I've found to date.
Ensure you are using SSL for all operations involving user information. All pages that involve these forms should check they are being called via HTTPS, and refuse to work otherwise.
You can eliminate most attacks by simply limiting the number of failed logins allowed.
Allow for relatively weak passwords, but store the number of failed logins per user and require a captcha or password verification by email if you exceed it. I set my max failures to 5.
Presenting login failures to the user needs to be carefully thought out as to not provide information to attackers.
A failed login due to a non existent user should return the same message as a failed login due to a bad password. Providing a different message will allow attackers to determine valid user logins.
Also make sure you return exactly the same message in the event of a failure for too many logins with a valid password, and a failure with too many logins and a bad password. Providing a different message will allow attackers to determine valid user passwords. A fair number of users when forced to reset their password will simply put it back to what it was.
Unfortunately limiting the number of logins allowed per IP address is not practical. Several providers such as AOL and most companies proxy their web requests. Imposing this limit will effectively eliminate these users.
I've found checking for dictionary words before submit to be inefficient as either you have to send a dictionary to the client in javascript, or send an ajax request per field change. I did this for a while and it worked ok, but didn't like the traffic it generated.
Checking for inherently weak passwords minus dictionary words IS practical client side with some simple javascript.
After submit, I check for dictionary words, and username containing password and vice versa server side. Very good dictionaries are readily downloadable and the testing against them is simple. One gotcha here is that to test for a dictionary word, you need to send a query against the database, which again contains the password. The way I got around this was to encrypt my dictionary before hand with a simple encryption and end positioned SALT and then test for the encrypted password. Not ideal, but better than plain text and only on the wire for people on your physical machines and subnet.
Once you are happy with the password they have picked encrypt it with PHP first, then store. The following password encryption function is not my idea either, but solves a number of problems. Encrypting within PHP prevents people on a shared server from intercepting your unencrypted passwords. Adding something per user that won't change (I use email as this is the username for my sites) and add a hash (SALT is a short constant string I change per site) increases resistance to attacks. Because the SALT is located within the password, and the password can be any length, it becomes almost impossible to attack this with a rainbow table.
Alternately it also means that people can't change their email and you can't change the SALT without invalidating everyone's password though.
EDIT: I would now recommend using PhPass instead of my roll your own function here, or just forget user logins altogether and use OpenID instead.
My Jqueryish client side password meter. Target should be a div. It's width will change between 0 and 100 and background color will change based on the classes denoted in the script. Again mostly stolen from other things I've found:
从根本上讲,您要防止主要类型的攻击
为了防止第一种攻击,您需要考虑包含弱常用单词的密码。为了防止第二种情况,您需要鼓励使用合理长度的密码(常见的是 8 个以上字符)和相当大的字符集(包括字母、数字和特殊字符)。如果您认为小写和大写字母不同,则会大大增加字符集。但是,这会给某些用户社区带来可用性问题,因此您需要平衡这种考虑。
快速谷歌搜索找到了可以解决暴力攻击(复杂密码)但不能解决字典攻击的解决方案。 PHP 密码强度计来自 此列表强度检查器在服务器端运行检查,因此可以扩展到检查字典。
编辑:
顺便说一句...您还应该限制每个用户的登录尝试次数。这将降低这两种类型的攻击的可能性。有效但不用户友好的方法是在 X 次错误尝试后锁定帐户并要求重置密码。更用户友好但更多的努力是限制登录尝试之间的时间。您还可以在前几次登录尝试后要求 CAPTCHA (这是 Stack Overflow 在进行过多编辑后所要求的) ,或对于新用户)。
Fundamentally you want to prevent to major types of attacks
To prevent the first, you want to consider passwords containing common words weak. To prevent the second, you want to encourage passwords of reasonable length (8+ characters is common) and with a reasonably large character set (include letters, numbers, and special characters). If you consider lower case and upper case letters to be different, that increases the character set substantially. However, this creates a usability issue for some user communities so you need to balance that consideration.
A quick google search turned up solutions that account for brute force attacks (complex password) but not for dictionary attacks. PHP Password Strength Meter from this list of strength checkers runs the check server-side, so it could be extended to check a dictionary.
EDIT:
By the way... you should also limit the number of login attempts per user. This will make both types of attacks less likely. Effective but not-user-friendly is to lock an account after X bad attempts and require a password reset. More user friendly but more effort is to throttle time between login attempts. You can also require CAPTCHA after the first few login attempts (which is something that Stack Overflow requires after too many edits, or for very new users).
基本上,您可能想使用正则表达式来验证密码的长度和复杂性。
可以在这里找到使用 javascript 执行此操作的一个很好的示例:
http://marketingtechblog.com/programming /javascript-密码强度/
Basically you probably want to use Regular Expressions to validate the length and complexity of the password.
A good example doing this using javascript can be found here:
http://marketingtechblog.com/programming/javascript-password-strength/
正如 Daren Schwenke 指出的那样,您最好自己解决安全问题,而不是将其交给用户。
但向用户提供一些关于其密码强度的提示是件好事,因为获取密码的最佳方式仍然是社交工程。
因此,您可以破解一个小客户端脚本,实时检查用户密码强度作为礼貌指示器。它不会阻挡任何东西,但当它变成绿色时,会给他一种温暖的感觉:-)
基本上你必须检查的是常识:检查密码是否包含合理数量的字母、数字和非字母字符。
你可以很容易地破解你自己的算法:只需做 10 / 10 标记:
您不需要检查神一般的密码(是否有大写字母,特殊字符的位置等),您的用户不在银行/军事/特工/每月蟒蛇电影行业,是吗?
您可以在一小时内编写代码,无需疯狂的 JavaScript 技能。
无论如何,验证密码并在服务器端移动所有安全代码。如果您可以委托身份验证(例如:开放 ID),那就更好了。
As Daren Schwenke pointed it out, you'd better work on the security yourself and not put this in the user hands.
But it's good to provide some hints to the user of how strong his password is, because the best way to get a password is still social engenering.
So you can hack a little client side script that checks the user password strenght as a courtesy indicator, in real time. It blocks nothing, but gives him a good warm feeling when it turns green :-)
Basically what you must check is commom sense : check if the password contains letters, numbers and non alphabetical caracters, in a reasonable quantity.
You can hack your own algo very easily : just make 10 / 10 mark :
You don't need to check for godlike passwords (are there capitalized letters, where are positioned the special caracters, etc), your users are not in the bank / military / secret service / monthy python movies industry, are they ?
You can code that in an hour in without crazy javascript skills.
And anyway, valid the password and move all the security code on the server side. If you can delegate authentification (e.g : open ID), even better.
不要自己动手!
密码学专家不鼓励自行开发密码学,原因如下这应该是显而易见的。
出于同样的原因,人们不应该尝试推出自己的解决方案来解决测量密码强度的问题;这在很大程度上是一个密码学问题。
不要陷入为此目的编写大量正则表达式的丑陋行径;您可能无法考虑影响密码整体强度的几个因素。
这是一个困难的问题
测量密码强度的问题本身就存在相当大的困难。我对这个主题进行的研究越多,我就越意识到这是一个“单向”问题;也就是说,人们无法有效测量破解密码的“难度”(计算成本)。相反,提供复杂性要求并衡量密码满足这些要求的能力会更有效。
当我们从逻辑上考虑这个问题时,“可破解性指数”并没有多大意义,尽管听起来很方便。驱动计算的因素有很多,其中大部分与专用于破解过程的计算资源有关,因此不切实际。
想象一下,John the Ripper(或类似的工具)与有问题的密码进行比较;破解一个像样的密码可能需要几天的时间,破解一个好的密码可能需要几个月的时间,甚至要等到太阳耗尽才能破解一个特殊的密码。这不是测量密码强度的实用方法。
从另一个方向解决问题要容易得多:如果我们提供一组复杂性要求,就可以非常快速地判断密码的相对强度。显然,所提供的复杂性要求必须随着时间的推移而发展,但如果我们以这种方式处理问题,需要考虑的变量要少得多。
可行的解决方案
Openwall 提供了一个名为
passwdqc
的独立实用程序(大概是,代表密码质量检查器)。 Openwall 开发者 Solar Designer 确实是一位真正的密码学专家(他的作品不言而喻),因此有资格编写这样一个工具。对于我的特定用例来说,这是一个比使用位于 Web 某个黑暗角落中的构思不周的 JavaScript 片段更具吸引力的解决方案。
为您的特定需求建立参数是最困难的部分。实施是最简单的部分。
一个实际示例
我在 PHP 中提供了一个简单的实现来提供快速入门。标准免责声明适用。
此示例假设我们将完整的密码列表提供给 PHP 脚本。不言而喻,如果您使用真实密码(例如,从密码管理器中转储的密码)执行此操作,则在密码处理方面应格外小心。简单地将未加密的密码转储写入磁盘会危及密码的安全!
passwords.csv
:password-check.php
:结果
report.csv
:总结
我还没有找到更彻底的解决方案网络;不用说,我欢迎任何其他建议。
显然,这种方法对于某些用例来说并不理想(例如,“客户端”实现的“密码强度计”)。即便如此,使用上述方法对服务器端资源进行 AJAX 调用并返回通过/失败响应也是微不足道的,但这种方法应该假设有滥用的可能性(例如,DoS 攻击),并且需要客户端和服务器之间的安全通信,以及接受与传输未散列密码相关的风险。
Don't Roll-Your-Own!
Cryptography experts discourage roll-your-own cryptography for reasons that should be obvious.
For the very same reasons, one should not attempt to roll his own solution to the problem of measuring a password's strength; it is very much a cryptographic problem.
Don't get into the ugly business of authoring some massive regular expression for this purpose; you will likely fail to account for several factors that influence a password's overall strength.
It's a Difficult Problem
There is considerable difficulty inherent to the problem of measuring a password's strength. The more research I perform on this subject, the more I realize that this is a "unidirectional" problem; that is, one cannot measure the "difficulty" (computational cost) of cracking a password efficiently. Rather, it is more efficient to provide complexity requirements and measure the password's ability to meet them.
When we consider the problem logically, a "crackability index" doesn't make much sense, as convenient as it sounds. There are so many factors that drive the calculation, most of which relate to the computational resources devoted to the cracking process, so as to be impractical.
Imagine pitting John the Ripper (or a similar tool) against the password in question; it might take days to crack a decent password, months to crack a good password, and until the sun burns-out to crack an exceptional password. This is not a practical means by which to measure password strength.
Approaching the problem from the other direction is far more manageable: if we supply a set of complexity requirements, it's possible to judge the relative strength of a password very quickly. Obviously, the supplied complexity requirements must evolve over time, but there are far fewer variables for which to account if we approach the problem in this way.
A Viable Solution
There is a standalone utility available from Openwall entitled
passwdqc
(presumably, standing for Password Quality Checker). Openwall developer, Solar Designer, does appear to be a bona fide cryptography expert (his works speak for themselves), and so is qualified to author such a tool.For my particular use-case, this is a far more attractive solution than using an ill-conceived JavaScript snippet living in some dark corner of the Web.
Establishing parameters for your particular needs is the hardest part. The implementation is the easy part.
A Practical Example
I offer a simple implementation in PHP to provide a jump-start. Standard disclaimers apply.
This example assumes that we're feeding an entire list of passwords to the PHP script. It goes without saying that if you are doing this with real passwords (e.g., those dumped out of a password manager), extreme caution should be exercised with regard to password-handling. Simply writing the unencrypted password dump to disk jeopardizes the security of your passwords!
passwords.csv
:password-check.php
:Resultant
report.csv
:Wrapping-Up
I have yet to find a more thorough solution on the Web; needless to say, I welcome any other recommendations.
Obviously, this approach is not ideal for certain use-cases (e.g., a "password strength meter" implemented "client-side"). Even so, it would be trivial to make an AJAX call to a server-side resource that returns a pass/fail response using the approach outlined above, but such an approach should assume the potential for abuse (e.g., DoS attacks) and would require secure communication between client and server, as well as acceptance of the risks associated with transmitting the un-hashed password.
我想不出一种特定的算法来检查密码的强度。我们所做的是定义几个标准,当密码符合某个标准时,我们将其分数加 1。当密码达到阈值时,密码就很强大。不然就弱了。
如果具有不同的阈值,您可以定义许多不同的强度级别,或者您可以为特定标准定义不同的值。例如,如果密码有 5 个字符,我们添加 1,但如果有 10 个字符,则添加 2。
这是检查
长度的标准列表(8 到 12 可以,越多越好)
包含小写字母
包含大写字母
大写字母不是第一个。
包含数量
包含符号
最后一个字符不是类似人类的符号(例如:.或!)
看起来不像字典里的单词。一些明智的密码破解包含单词和字母替代库(例如 Library --> L1br@ry )
希望有所帮助。
I can't think of a specific algorithm to check the strengh of a password. What we do is we define several criterion and when the password respect a criteria, we add 1 to its score. When the password reach a threshold, the password is strong. Otherwise it is weak.
You can define many different level of strengh if with different throeshold, or you can define different value for a specific criteria. For example, if a password has 5 character, we add 1, but if it got 10, then we add 2.
here is a list of criterion to check for
Length (8 to 12 is ok, more is better)
Contains lowercase letter
Contains uppercase letter
The upper case letter is NOT the first one.
Contains number
Contains symbols
the last character is NOT a human like symbol (ex : . or !)
Does not look like a dictionnary word. Some wise password crack contains library of word and letter substitutes (like Library --> L1br@ry )
Hope that help.