Spiga

md5/sha1+salt和Bcrypt

2011-12-24 04:04 by lixiong, 2710 visits, 收藏, 编辑

今天在weibo.com上看到一则消息说, md5/sha1+salt的方法保存密码是不安全的. 文章中用连续9Bcrypt加感叹号来强调, 保存密码一定要用Bcrypt.

这个消息非常应景, 因为csdn.net两天前把数据库弄丢了, 里面的密码是明文保存的. 我对密码和安全没有研究, 但是在我粗浅的记忆中, hash+salt是非常主流的方法. 如果说这样也不靠谱, 那我正好借这个机会复习一下.

我把密码安全分为两个等级, 黄色和红色. 当数据库丢失后, 能算出一个可以用来登陆的密码, 这个密码不一定是原文, 但是保证可以通过验证, 这个算达到黄色. 如果还能算出原文, 这个就达到了红色.

红色比黄色严重得多. 因为用户往往在多个网站上都使用了同样的密码. 如果攻击者拿到原文, 这等于说多个网站都受到影响了. 如果拿不到原文, 那攻击者最多也就破坏当前这个泄露数据库的网站, 不会影响到其它网站.

在我看来, 很多用户对安全的要求是, 如果我使用的网站A不幸阵亡了, 只要密码原文不泄漏, 就不会伤及我使用同样密码注册的其它网站. 至于在网站A上面的任何损失, 我都不在乎了.

在这个背景下, 我的本能看法是, hash+salt难道不能实现上述的要求, 一定要使用Bcrypt?

如果仔细分析一下黄色和红色的定义, 会发现一个问题. 对于一个给定的可以用来登陆的密码, 如何判定这个密码就是原文呢? 这里的解决方法通常就是对比字典, 或者观察这个密码的字面特性.

既然牵涉到字典, 情况就更加有趣了. 破解密码的两种方法分别是穷举和字典. 我从wikipedia以及介绍上Bcrypt的资料上了解到, 如果只是穷举, hash+48位的salt算起来已经比较困难了. 文章中说,半分钟可以穷举完所有的6位密码。可以想象,如果加上一个48位的salt, 按照复杂度的增加比例,要穷举完所有可能的密码,至少还是要按月算计算的吧。

在这样的情况下,如果要想得到密码原文,首先需要花大量时间把很多可能的密码都算出来,然后才能挑选原文。就算用集群计算机,这个也需要几天时间吧。我想也不是所有用户都能享受到这个待遇的吧。如果这条路走不成,那就只有反过来,根据现成的字典来算。如果不幸使用了字典中能查到的就活该倒霉了。

当然,上面的假设是窃密者不知道salt的情况. 如果salt一起丢了的话, salt对单个用户的保护就完全丢失了。这个情况下salt的作用是让窃密者必须对每个用户都单独计算。但是即便是这样,如果密码稍微复杂一点,用8位数字字母组合,暴力走一遍也需要608次方除以700M,结果是66小时。实际时间应该比这个更长一点,因为这个时间没有考虑到长度小于8位的。

为了证明我的想法,我特意花了20大洋,到http://cmd5.com/ 这个网站上买了4次破解机会。我提交了一个123456作为原文,12salt计算出来的密文。另外再提交了一个8位包含大小写数字和一个@字符的原文,12位同样salt计算出来的密文。提交的时候把salt一起提交的。明天我再看看他能计算出怎样的结果。

根据上面的分析,使用hash+salt的话,在不同情况下有不同的结果:

如果salt没有丢,除非你的确是机要人员,基本上安全。普通cracker不会花这么多精力来搞你。

如果salt丢了,情况根据密码复杂度来看。简单密码就秒破到原文了。对于8位普通程度的密码,比如315@hkBJ这样的密码,对方可以在几个小时内走到黄色等级,但需要2天时间才能开始分析原文。

再来看看使用Bcrypt的话,情况会有如何变化。Bcrypt其实是通过增加计算密文的成本来换取安全。使用Bcrypt,默认设置下登陆时间会增加5个数量级,破解成本也会增加5个数量级。所以使用Bcrypt的话,根据我的理解,情况分为两种:

如果Bcryptsalt丢了,使用简单密码或者字典中存在的密码,秒破的时间从小于一分钟变到几天时间。所以使用简单密码还是不安全的。但是如果salt没有丢,或者即便丢了但是使用了稍微复杂的密码,要达到黄色平均时间都上年了,要到红色就不可能了。

所以,总的结论是:

如果使用不安全的密码,什么都帮不上忙。

如果使用hash+salt, 事故发生的时候,如果salt丢了,算法也没有特殊的地方,只要遇上专业人员,如果密码在8位以内,要拿到可能的密码原文,基本上是一个星期的工作。我估计花1W RMB应该能找到人干。但是如果密码里面的特殊字符多一点,或者长度再长一点,基本就安全了,除非你是重要人物。

如果使用Bcrypt,那当然最好了。丢了什么都不怕。但是,使用Bcrypt的成本是,负责做认证的服务器,可能要扩容几十倍或者几百倍哦,它是靠把计算成本提高5个数量级来换取安全的。

 

作为设计人员,使用Bcrypt肯定安全很多。但是安全的代价是性能。小型的应用没有问题,但如果每秒峰值要做到上万次登陆呢?毕竟每次登录默认0.3秒的开销摆在那里,一万次是3000秒,如果要保证登陆在1秒内完成,须要3000个服务器啊。所以在大一点的应用上使用Bcrypt,登陆服务器的设计和Bcrypt参数的配置都要仔细考量。在这样的权衡下,我觉得使用hash+salt仍旧是不错的选择. 前提是要做到如下几点: salt单独存放,使用SHA512, 独立设计hash方法比如salt插到password中间,多做几层hash,另外把代码和数据库分开存放。

 

下面这篇文章详细分析了Bcrypt的性能。得到的结论是除非你给五角大楼写程序,通常的SHA512足够好了。 

 http://www.binarylogic.com/2008/11/22/storing-nuclear-launch-codes-in-your-app-enter-bcrypt-for-authlogic/ 

The level of security your app provides is really up to you. Unless you are writing apps for the pentagon, the default Sha512 is fine. Regardless, Authlogic shouldn’t get in your way or make decisions for you, so if you feel BCrypt is necessary then go for it.” 

 

作为用户来讲,主要是做到两点。首先要使用比较复杂的密码,其次是不同安全级别的网站要使用不同的密码。比如国内网站和国外网站坚决不用一样的。银行密码不用一样的。如果注册使用邮箱作为源,那这个源的密码要特别设计。

以上就是今天晚上研究了4个小时的收获。看来我7年前了解到的hash+salt,在新时代的计算能力面前的确比较脆弱了。我算重新入门了一次。多谢 @左耳朵耗子.

相关资料:

http://codahale.com/how-to-safely-store-a-password/

http://en.wikipedia.org/wiki/Bcrypt

http://en.wikipedia.org/wiki/Rainbow_table

http://en.wikipedia.org/wiki/Salt_(cryptography)

http://cmd5.com/

 

Add your comment

9 条回复

  1. #1楼 说不得      2011-12-24 09:50
    为什么说md5/sha1+salt不安全呢?微薄原链接是哪里?
    这个md5/sha1+salt的用法是怎样的呢?

    我理解的salt方法是这样的md5(md5(明文)+salt),这样就算你知道了salt又如何。
    我们用一个典型的弱密码123456来测试,登录cmd5网站,在输入框中输入123456,这时网站会自动输出md5:49ba59abbe56e057,我们把md5值粘贴到输入框中,点击解密,立即就出现了明文123456,说明这个密码真的很不安全。
    接下来,我们在输入框中刚才的md5值后面接着输入1111,相当于我们在密码123456的基础上加了4位salt,这时网站自动输出md5:03a5696a6c83cc03,我们把这个md5值粘贴到输入框,点击解密,会提示你破解进度0%,需要你登录或付费。
    而且我们刚才使用的是16位md5,加上4位salt,相当于把密码设置为20位字母+数字,破解这种密码,就算知道了salt,又有何用?
     回复 引用 查看   
  2. #2楼 PetterLiu      2011-12-24 10:03
    一般应用,SHA512+SALT已经足够了
     回复 引用 查看   
  3. #3楼 Microshaoft      2011-12-24 11:24
    如果使用“键控哈希”

    md5(user+pass) 作为键
    再计算一次hmac
    hmac(user+pass)
     回复 引用 查看   
  4. #4楼 Astar      2011-12-24 13:16
    嗯,现在连SALT也没用,考虑加上这个...定期更新SALT和它的位置,每次更新选个时间同步一下数据库。
     回复 引用 查看   
  5. #5楼 今昭      2011-12-24 20:27
    引用说不得:
    为什么说md5/sha1+salt不安全呢?微薄原链接是哪里?
    这个md5/sha1+salt的用法是怎样的呢?

    我理解的salt方法是这样的md5(md5(明文)+salt),这样就算你知道了salt又如何。
    我们用一个典型的弱密码123456来测试,登录cmd5网站,在输入框中输入123456,这时网站会自动输出md5:49ba59abbe56e057,我们把md5值粘贴到输入框中,点击解密,立即就出现了明文123456,说明这个密码真的很不安全。
    接下来,我们在输入框中刚才的md5值后面接着输入1111,相当于我们在密码123456的基础上加了4位salt,这时网站自动输出m...

    你说的是盗取的人不知道你的加密算法,而事实上盗取人的第一步就是通过他有的明文密码来破解加密公式,如果是你这种公式则不存在破解公式的难度,你连salt也丢了,那破解公式就更容易了。当公式破解了后md5几次已经没有意义,现在已经有专门的文献说明md5多少次是达不到想象中的效果,保管好salt才是性价比最高的王道。
     回复 引用 查看   
  6. #6楼 说不得      2011-12-24 21:33
    引用今昭:
    引用说不得:
    为什么说md5/sha1+salt不安全呢?微薄原链接是哪里?
    这个md5/sha1+salt的用法是怎样的呢?

    我理解的salt方法是这样的md5(md5(明文)+salt),这样就算你知道了salt又如何。
    我们用一个典型的弱密码123456来测试,登录cmd5网站,在输入框中输入123456,这时网站会自动输出md5:49ba59abbe56e057,我们把md5值粘贴到输入框中,点击解密,立即就出现了明文123456,说明这个密码真的很不安全。
    接下来,我们在输入框中刚才的md5值后面接着输入1111,相当于我们在密码123456的基础上加了4位sal...

    你理解错了,加密的安全性并不依赖于加密的算法。
     回复 引用 查看   
  7. #7楼 sunriseyuen      2011-12-25 11:45
    知道了算法,丢失了salt,然后用csdn 600万的密码库选出常用密码穷举,估计也不需要很就,就可以破解到常用密码。所以不要使用常用密码就会相对安全些。
     回复 引用 查看   
  8. #8楼 imfunny      2011-12-25 14:11
    同意六楼的。密的安全性并不依赖于加密的算法。
    不需要那么复杂。考虑hash+md5吧。
     回复 引用 查看   
  9. #9楼 Zealic      2011-12-25 17:07
    Hash 和 Salt 依然很难破解。
    这点安全性依然可靠
    因为对方并不知道你如何 Hash,是将 Pass 取二进制连接 salt 再hash,或者将 salt base64 后 hash,甚至将 salt hash 后再同 pass hash.

    我认为的一种安全性较高的做法是:
    1.取 Pass bytes
    2.取 Salt 并通过密钥加密
    3.将 Pass 与 Salt 连接并Hash(也可加上上述提出的步骤)

    这样安全性提高,基本无法还原与暴力攻击,攻击者想要验证必须获得密钥才能进行验证。
    想要更高的安全性,可以逻辑隔离密钥加密的过程,通过内部的加密服务进行Salt 加密。
    如果有上级需求明文密码,可将加密过程改为非对称加密,内部加密服务使用公钥进行加密,私钥则只有少数人持有(可开发一个内部查询服务,使用该私钥解密查询明文密码)。
     回复 引用 查看