2009-09-24 79 views
12

加入我与弱密码哈希的斗争。是否有使用PBKDF2作为密码哈希的标准?

PBKDF2密码散列应包含salt,迭代次数和散列本身,以便稍后进行验证。是否有标准格式,例如RFC2307的{SSHA},用于PBKDF2密码哈希值? BCRYPT很棒,但PBKDF2更容易实现。

显然,没有规范。所以这是我的规格。

>>> from base64 import urlsafe_b64encode 
>>> password = u"hashy the \N{SNOWMAN}" 
>>> salt = urlsafe_b64decode('s8MHhEQ78sM=') 
>>> encoded = pbkdf2_hash(password, salt=salt) 
>>> encoded 
'{PBKDF2}1000$s8MHhEQ78sM=$hcKhCiW13OVhmLrbagdY-RwJvkA=' 

更新:http://www.dlitz.net/software/python-pbkdf2/定义crypt()更换。我更新了我的小规格以匹配他,除了他以$p5k2$开头,而不是{PBKDF2}。 (我需要迁移其他LDAP风格的{SCHEMES})。

这是{PBKDF2},在小写十六进制,$迭代次数,则urlsafe_base64编码盐,$urlsafe_base64编码PBKDF2输出。 salt应该是64位,迭代次数应该至少为1000,并且HMAC-SHA1输出的PBKDF2可以是任何长度。在我的实现中,默认情况下总是20个字节(SHA-1哈希的长度)。

在通过PBKDF2发送密码之前,必须将密码编码为utf-8。没有关于是否应将其规范化为Unicode的NFC。

这个方案应该比次更加昂贵,因为蛮力比{SSHA}要贵。

+1

我写了这段代码之后的一段时间,我意识到RedHat Linux中使用的基于SHA的隐藏替换。它可能比有问题的PBKDF2方案设计得更好。 http://en.wikipedia.org/wiki/Crypt_%28Unix%29#SHA-based_scheme – joeforker 2010-08-31 19:40:43

回答

4

PBKDF2的参数(盐和迭代)有一个规范,但它不包含散列。这包括在PKCS #5 version 2.0中(见附录A.2)。一些平台已经内置了对这个ASN.1结构进行编码和解码的支持。

因为PBKDF2实际上是一个密钥派生函数,所以指定一种方法将“散列”(实际上是派生的密钥)与正常使用中的派生参数—捆绑在一起的方式是没有意义的,密钥必须保密,并且永远不会被存储。

但是,作为单向密码散列的使用,散列可以存储在带有参数的记录中,但存储在它自己的字段中。

4

我会和你一起对抗弱哈希值。

OWASP有一个密码存储备忘单(https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet)和一些指导;他们建议至少2012年至少进行64,000 PBKDF2迭代,每两年翻一番(即2012年为90,510)。

请注意,每个用户存储一个长密码随机盐总是基本的。

请注意,具有广泛变化的每用户迭代次数和存储迭代次数以及salt会增加一些复杂程度以破解软件,并可能有助于排除某些优化。例如,“bob”被135817次迭代加密,而“alice”使用95,121次迭代,也就是2013年的最小值(90510 + RAND(90510))。

还要注意,如果用户可以选择弱密码,如“密码”,“密码1!“,”P @ $$ w0rd“和”P @ $$ w0rd123“,所有这些都可以通过基于规则的字典攻击很快找到(后者简单地是”密码“,具有以下规则:大写的第一个字母,以1337为例,在最后添加一个三位数的数字),用一个基本的词典列表(phpbb,用于一个好的,小的首字母词表),并将这样的规则应用于它,并且你会在人们尝试的时候破解很多密码“巧”的技巧

因此,在检查新密码时,不要仅仅应用“上,下,数字,数字,至少11个字符长度的所有四个”,因为“P @ $$ w0rd123”符合这个看似非常棘手的规则,相反,使用这个基本的字典列表,看看基本规则是否会破解它(这比实际尝试破解要简单得多 - 你可以降低你的列表和他们的单词,然后简单地编写像“如果最后4个字符是一个常见的年份,chec k除了最后4个字符以外的所有字符“,以及”如果最后3个字符是数字,检查除了最后3个字符之外的所有字符“和”检查除了最后两个字符之外的所有字符“和” 1337的密码 - 把@变成a,把3变成e等等,然后根据单词表检查它,并尝试其他规则。“

就口令而言,总的来说,这是一个好主意,特别是如果其他字符被添加到单词的中间,但是当且仅当它们足够长时,因为你放弃了很多可能的组合。

请注意,即使在2012年,具有GPU的现代机器每秒钟也要达到数百亿次散列迭代(MD5,SHA1,SHA-256,SHA-512等)。至于字组合“correct马电池钉“型密码,这个密码最多只是一个非常适中的密码 - 它只有4个全部小写英文单词,长度不超过7个空格。所以,如果我们去寻找XKCD风格的密码,其猜测次数为180亿次:一个现代的小美国英语字典有:6k字长度5或更少21k字长7或更少36k字长9或更少46k字长度不超过11​​个或更少49k个单词的长度不超过13个或更少

使用XKCD风格的密码短语,并且不打扰按照流行度来过滤单词(“正确”与“椅子”对比“兜风”与“出血”)我们有21k^4,这只有2E17的可能性。在180亿/秒的设置下(如果我们面对单个SHA1迭代,一台带有8颗GPU的机器),大约需要4个月时间来彻底搜索密钥空间。如果我们有十个这样的设置,那大约两个星期。如果我们排除不太可能的单词,比如“dumpier”,那么快速首发就快很多了。

现在,如果您从“巨大的”linux美式英语单词列表中获得单词,例如“Balsamina”或“Calvinistically”(均通过使用“go to row”功能选择),那么我们将有30k个单词长度5或更小115k字长7或更小231k字长9或更小317k字长11或更小362k字长13或更小

即使有7个长度的最大限制,一个基地和随机选择的单词,我们有115k^4 = 1.8E20的可能性,或者如果设置保持最新(每18个月增加一倍的功率),则约12年,这与13个字符的小写字母非常相似+ number only password。“300 years”是大多数人估计会告诉你的,但他们没有考虑到摩尔定律

+1

该备忘单看起来很有用。你的文章在半句话结束后,你能解决吗?另外,您如何看待passPHRASES而不是passWORDS?请参阅http://xkcd.com/936/ – 2013-01-02 16:56:29

+1

我只是将@ Anti-weakpasswords的两个半答案合并为一个答案。我没有做任何改变,只是复制了另一篇文章并粘贴在这里。 – user9876 2013-03-27 02:22:57