关于 md5 密码加密的一点小疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
binbinyouliiii
V2EX    Java

关于 md5 密码加密的一点小疑问

  •  
  •   binbinyouliiii 2016-08-22 14:43:50 +08:00 13534 次点击
    这是一个创建于 3365 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在很多公司都用 md5 加密来加密密码,我们公司也是用的这个方式(不是我写的),众所周知, md5 是不可逆的,所以存在数据库的密码是加密的,如果用户从前台传来密码,按我现在所知的应该只能从传来的密码再加密后和数据库进行比较。
    前几天又看到有一个叫彩虹表的东西,觉得跟字典差不多,那这样岂不是很不安全,既然 md5 不可逆,那为什么公司都不自己随便创个加密方式,非要用 md5 ,有了彩虹表这个东西, md5 又比普通的加密安全吗?


    刚实习的新手,有小白的地方轻喷

    第 1 条附言    2016-08-22 19:55:52 +08:00
    话说 v 站的朋友都对 java 很排斥吗,之前看过几篇帖子,评论或多或少都对 java 又点排斥
    105 条回复    2016-08-24 23:33:28 +08:00
    1  2  
    reyoung1110
        1
    reyoung1110  
       2016-08-22 14:46:22 +08:00   1
    md5 不是加密算法,是 hash 算法。
    qiayue
        3
    qiayue  
    PRO
       2016-08-22 14:49:05 +08:00
    在没有彩虹表,计算能力不强的年代,一个 md5 加密的确可以解决问题。
    后来随着计算能力的提升,人们把常见的字符组合都拿去 md5 跑一遍,生成彩虹表,简单的 md5 就没有用了。
    所以一般都需要加盐,并且每个用户的盐都不同。这样即使别人直接拿到了你的数据库数据,他也没办法根据彩虹表知道用户密码是啥了。
    jimzhong
        4
    jimzhong  
       2016-08-22 14:49:13 +08:00
    md5 不属于加密,因为散列函数的“值域”一定比它的“定义域”小,所以理论上是不可逆的。
    但是因为有彩虹表这个东西,单纯用 MD5 已经不安全了,所以一般都会加盐处理。楼主可以看一下 PBKDF 函数的设计。
    jugelizi
        5
    jugelizi  
       2016-08-22 14:51:52 +08:00
    因为很多程序员只会 md5
    不过新手能思考这些真不错了
    遇到七八年开发经验的都认为 md5 是来加密的
    jasonyang9
        6
    jasonyang9  
       2016-08-22 14:55:59 +08:00
    参考 Linux 中 shadow 的存放,都是加了随机盐的
    binbinyouliiii
        7
    binbinyouliiii  
    OP
       2016-08-22 14:57:16 +08:00
    @qiayue
    @jimzhong
    像 cmd5 这种网站是骗人的还是真的可以破解,破解是靠彩虹表,还是它们真的计算能力强大,能够把密码算出来,我看很多人用了这类网站一段时间后可以破解出来(虽然收费)
    otakustay
        8
    otakustay  
       2016-08-22 14:59:00 +08:00
    首先,你要有“随手创个加密方式”的能力,我大学自学密码学一年多还是创造不出可靠的算法,怎么就随手了……
    gdtv
        9
    gdtv  
       2016-08-22 14:59:57 +08:00
    因为 md5 加密方式很完善,你自己创一个新的加密方式可能有漏洞。
    因为有彩虹表,所以 md5 加密的时候必须要加盐,加盐后的安全性强于你自己创一个新的加密方式。
    以前 wuyu 上面有篇文章详细解释了为什么不应该自己创建加密函数,可惜那个网站……
    murmur
        10
    murmur  
       2016-08-22 15:00:21 +08:00
    @binbinyouliiii 等你到了企业里就知道了 用简单密码的大有人在 很多系统密码都有个默认的 123456 什么 然后因为开发测试我们会借其他人的正式账户用
    不改密码用 123456 的大有人在
    jimzhong
        11
    jimzhong  
       2016-08-22 15:01:59 +08:00
    @binbinyouliiii 我估计是用彩虹表,但是它的彩虹表规模会很大,以至于要收费。如果要验证用户密码还是推荐 PBKDF 。
    ostholz
        12
    ostholz  
       2016-08-22 15:02:01 +08:00
    加密密码段, 一般用 bcrypt 比较好. MD5 的算法已经被优化到极至了, 彩虹码加暴力破解很可能很快就算出.
    bcrypt 算一个密码的时候是固定的, 暴力破解对它起不了作用.
    jarlyyn
        13
    jarlyyn  
       2016-08-22 15:03:38 +08:00
    salt 再加 salt
    binbinyouliiii
        14
    binbinyouliiii  
    OP
       2016-08-22 15:06:30 +08:00
    @otakustay 我也不了解算法什么的,我之前认为如果对原文做一些操作,比如原文第 2 个字符加一什么的,一般不知道的人也没法破解,算法有漏洞啥的更是不了解,原谅我小白
    ma125125t
        15
    ma125125t  
       2016-08-22 15:08:34 +08:00
    @jarlyyn 要是这样为何不直接用加密算法呢
    jimzhong
        16
    jimzhong  
       2016-08-22 15:08:56 +08:00
    @binbinyouliiii 如果感兴趣可以阅读一下 William Stallings 的《密码编码学与网络安全》。
    jimzhong
        17
    jimzhong  
       2016-08-22 15:10:05 +08:00
    @ma125125t 如果拖库加密密钥也很可能被对方知道。
    jarlyyn
        18
    jarlyyn  
       2016-08-22 15:12:21 +08:00
    @ma125125t

    md5 并不是加密,还是取特征值。

    加 salt 是为了让原始密码混淆,不容易被识别。
    xcodeghost
        19
    xcodeghost  
       2016-08-22 15:15:52 +08:00
    很多私人创建的加密算法,其实并不如一些主流的加密算法来得可靠。毕竟主流的加密算法在全球大范围的使用,如果有漏洞应该很快就会被发现了。自己创建的加密算法,除非很完美,否则不建议使用。
    loading
        20
    loading  
       2016-08-22 15:19:56 +08:00 via Android
    加盐,也就是你在用户的密码后面附加一个一定长度的字符串,有全网用同一个的,还有就是随机生成(记得一起存到数据库)每一个都不同。

    然后对这个合成的密码进行 md5,一般会使用多次 md5 的方式,防止被彩虹表命中,或者被人撞库(应该没人会这样验证)


    你用 md5 生成的,是没法算出原文的。

    除非彩虹表。就是一个保存有原文和对应 md5 的表格,从里面查出来。而这个原文字符串也并不是机器穷苦出来的,而是从像 csdn 前期泄漏出的使用明文保存密码里面生成出来的,很多人的密码要么和 csdn 一样,要么就碰巧 csdn 这些库里就有一样的。就像 123456 这个密码,你会用,别人也会用。
    loading
        21
    loading  
       2016-08-22 15:23:18 +08:00 via Android   1
    别人黑掉你的服务器,你的加密算法也就到手,拿到你的加密算法密钥也是分分钟的事,所以使用加密算法不见得比 md5 好。

    对用户密码加密,很多时候是为了保护用户的密码,而不是保护用户在你服务器的内容!
    ma125125t
        22
    ma125125t  
       2016-08-22 15:23:24 +08:00
    @jarlyyn 明白,使用 md5 或加盐的时候已经表明使用者不需要原文的任何信息,但希望结果是唯一值,是这个意思吧。
    sheep3
        23
    sheep3  
       2016-08-22 15:23:28 +08:00
    密码所在表添加一个字段 salt ,在登陆时通过用户名拿到 salt 再和传上来的密码进行拼接后求 MD5 ,再和数据库的 MD5 值比较.
    eliteYang
        24
    eliteYang  
       2016-08-22 15:23:53 +08:00
    加一个随机 salt
    jarlyyn
        25
    jarlyyn  
       2016-08-22 15:28:46 +08:00
    @ma125125t

    结果也不是唯一值。

    而是碰撞的概率足够小。
    ma125125t
        26
    ma125125t  
       2016-08-22 15:47:14 +08:00
    @jarlyyn 还有一个问题,没拿到盐的情况下,有办法获取加过盐的密码的散列值的原文吗?如果没办法,是否没必要加两次盐呢,或者说加两次盐的目的是防止第一个盐被获取的情况下进行再保护呢。不过盐又怎么会拿到呢,一般盐放在数据库中,拿到盐的时候已经拿到密码了吧?不知道我的理解有没有问题。
    imlonghao673
        27
    imlonghao673  
       2016-08-22 15:52:56 +08:00 via Android
    md5 的解密成本就是 cmd5 的价格
    lincanbin
        28
    lincanbin  
       2016-08-22 15:53:26 +08:00
    要发明一个 Hash 算法,你得先去证明它是 Hash 算法。
    Felldeadbird
        29
    Felldeadbird  
       2016-08-22 15:59:11 +08:00
    自己写的加密算法有一个可怕的地方在于,网站得漏洞让加密代码爆出的可能性。
    想想就觉得可怕了。你在某网站得密码,可以解密出来的……
    MD5 即使结合彩虹表,也不表示所有密码是由对应的。所以其实加点盐, MD5 目前足够使用的了。
    jarlyyn
        30
    jarlyyn  
       2016-08-22 16:06:30 +08:00
    @ma125125t

    盐和密码(特征码)是放在一起的。加盐就是为了数据库被拖库的情况下保证安全。

    一次加盐和两次加盐的安全性差不多。

    我只是为了以后可以本地存 hash 代替密码
    xi2008wang
        31
    xi2008wang  
       2016-08-22 16:16:19 +08:00   3
    转乌云的一篇很赞文章
    https://jiji262.github.io/wooyun_articles/drops/%E5%8A%A0%E7%9B%90hash%E4%BF%9D%E5%AD%98%E5%AF%86%E7%A0%81%E7%9A%84%E6%AD%A3%E7%A1%AE%E6%96%B9%E5%BC%8F.html

    核心观点:
    1 ,不要自创 hash 算法
    2 ,加盐,而且盐长度足够,至少要和 hash 输出一样长
    3 ,不要重复使用盐
    lance6716
        32
    lance6716  
       2016-08-22 16:19:38 +08:00 via Android
    科班出身是多么重要…
    damean
        33
    damean  
       2016-08-22 16:39:10 +08:00
    额,好多人似乎没有学过密码学。。。

    最后不建议自造算法,建议多看看书。
    qinxi
        34
    qinxi  
       2016-08-22 16:40:19 +08:00
    加盐,以及 hash 次数
    shiny
        35
    shiny  
    PRO
       2016-08-22 16:43:41 +08:00
    加盐;加随机盐
    Kantoi
        36
    Kantoi  
       2016-08-22 16:44:55 +08:00
    @xi2008wang 看的好爽
    jhdxr
        37
    jhdxr  
       2016-08-22 18:21:40 +08:00
    @binbinyouliiii 你“加密”(加引号,因为正确的说法是哈希)的意义在于把你的代码 /算法和数据都交给别人的情况下,别人依然无法轻易获得你用户的密码。为什么要把代码和数据给别人?因为你有信心永远不被黑么。。。


    然后再来说一些上面已经有人提到的内容。彩虹表的原理是什么?因为 md5 的结果是确定的,也就是说对于 A 输入,它得出的结果一定是 A',那么我就可以预先计算好。这样子当你给我一个 md5 的结果时,我就能反向找出它对应的明文是什么。而且在实际上,很多人用的密码都很常见,所以很容易就被找到了(也就是破解了)

    然后就有了加盐的概念,既然用户自己的密码很容易被破解,那么我就在用户的密码上增加点什么。考虑到彩虹表的原理是预先算好,所以应对的方法很简单,我使用户的密码变得很长(例如在最后加上个 32 位字符串)。← 这也是为什么你提出的『用户密码第二位+1 』这种方案没有意义,在知道你的算法后,别人的计算量并没有提高

    然后之所以不要重复用盐, 是因为如果你对于所有用户的盐值都一样,那么入侵者就可以针对你的盐值,专门打造一份彩虹表来进行破解。而如果每个用户的盐值都不一样,那么他破解的代价将高很多很多( 不存在绝对安全的算法,我们能做的就是在自己能够承受的情况下,尽可能提高入侵者的成本)

    最后说下换算法以及加 hash 次数。 md5 之所以以前没问题,现在不行了的原因是计算力的不断提高。所以首先增加 hash 的次数这种做法是有意义的,因为它会增加彩虹表生成的时间。然而这种意义不大。。。因为计算力依然在继续提高。。。但这个思路是完全正确的,例如 bcrypt 或者 pbkdf2 都是这种思路。假如每次函数调用增加到半秒,对于正常的业务来说影响不大(只需要在登录时验证),但对于彩虹表来说,哪怕只计算 8 位的纯数字就需要 10,000,000*.5/86400=57.87 天了。别觉得这个时间好像很短,因为这只是 8 位纯数字,换成 8 位的数字+大小写字母就是 62^8*0.5/86400/365=3461759 年了。。。而且配合上面说的不要重复用盐,对于每个用户都重新计算彩虹表,这个代价就更加的大了。。。
    Halry
        38
    Halry  
       2016-08-22 18:27:07 +08:00
    md5 什么时候是加密的
    觉得至少也要 sha1 吧
    wy315700
        39
    wy315700  
       2016-08-22 18:27:59 +08:00
    @Halry sha 几都不是加密的
    youxiachai
        40
    youxiachai  
       2016-08-22 18:29:11 +08:00
    @lance6716 科班也没啥用吧..你读大学的时候有教这个...起码我大学老师..也是把 md5 管加密..我去吐槽他的时候.还不鸟我..
    Halry
        41
    Halry  
       2016-08-22 18:30:35 +08:00
    @wy315700 我的意思是 md5 是 hash 算法,根本没有加密功能,因为是不可逆转的.
    youxiachai
        42
    youxiachai  
       2016-08-22 18:30:43 +08:00
    @Halry 加密举个 aes 吧...sha 也是散列算法..
    Halry
        43
    Halry  
       2016-08-22 18:31:36 +08:00
    @youxiachai 看上一楼,表达错误,sorry
    wy315700
        44
    wy315700  
       2016-08-22 18:35:47 +08:00
    @youxiachai
    @Halry
    但是 SHA 算法其实是一个固定密钥的块加密算法
    morethansean
        45
    morethansean  
       2016-08-22 18:36:24 +08:00
    @Halry sha1 可逆?
    scnace
        46
    scnace  
       2016-08-22 18:37:27 +08:00 via Android
    md5 来做 Bloom filter 的散列函数不错 (还记得当年实验室开周技术分享的时候 因为说了 md5 是加密算法 被学长嘲笑的无地自容)
    lance6716
        47
    lance6716  
       2016-08-22 18:46:20 +08:00
    @youxiachai 学通信的,好多门课都会讲加密和消息摘要
    fyibmsd
        48
    fyibmsd  
       2016-08-22 18:49:30 +08:00
    这叫非对称加密
    wy315700
        49
    wy315700  
       2016-08-22 18:52:41 +08:00
    @fyibmsd 第一次听说非对称加密这么解释的
    raincious
        50
    raincious  
       2016-08-22 18:53:24 +08:00
    @Halry

    其实并不是说 Hash 不能用来做密码“加密”,只是说很多 Hash 算法太快了。密码的 Hash 算法需要能控制 Hash 计算的速度,原字符串输入进去之后,必须使用大于 N 的时间才能算出对应的 Hash ,这样才可以保证密码在 N 年内不太可能被破解出来。

    直接用 MD5 、 SHA1 的问题是,如果 Hash 拿到手,几分钟撞出一个,对于关键人物(比如各种 SSL 证书)来说跟没 Hash 过的完全没有区别。
    f2501093
        51
    f2501093  
       2016-08-22 19:05:48 +08:00
    TL; DR 直接用 bcrypt (如果你担心基于 ASIC 或者 FPGA 的硬件密码破解,用 scrypt )
    binbinyouliiii
        52
    binbinyouliiii  
    OP
       2016-08-22 19:08:23 +08:00 via Android
    @lance6716 额,我学 java 的,老师从来没提起过 md5 啥的,难道别的老师都教这个嘛
    paw
        53
    paw  
       2016-08-22 19:19:34 +08:00
    http://webcache.googleusercontent.com/search?q=cache:ezsTSZ3IZUEJ:blog.jobbole.com/87058/+&cd=1&hl=zh-CN&ct=clnk (源站打不开 贴快照了)
    http://coolshell.cn/articles/2078.html

    用 bcrypt 、用 bcrypt 、用 bcrypt
    别用 MD5 、 SHA1 、 SHA256 、 SHA512 、 SHA-3 等“加密”算法
    hack
        54
    hack  
       2016-08-22 19:30:45 +08:00
    md5(md5(pwd)+$%^*&) ,欢迎来解
    haozibi
        55
    haozibi  
       2016-08-22 19:32:44 +08:00 via Android
    还好我学过密码学,你可以百度一下,山大王小云
    Wien
        56
    Wien  
       2016-08-22 19:34:32 +08:00
    md5 、 sha1 这类算法都是单向哈希算法,不算加密。 bcrypt 是专门为密码存储而设计的算法。一般把密码 MD5 后的哈希值再用一次 bcrypt 加密,已经不可能被破解了。
    binbinyouliiii
        57
    binbinyouliiii  
    OP
       2016-08-22 19:39:22 +08:00
    @haozibi 哈哈,我一开始看成山大王 小云 了 shan dai wang xiaoyun
    damean
        58
    damean  
       2016-08-22 19:41:46 +08:00
    @binbinyouliiii
    额,学校里不都是教计算机网络的时候顺带教一下 java 的吗? java 这么简单,还有单独的课程么?
    我念书的时候,只有 C/C++有单独的课程。

    我上学的时候密码学虽然是选修,但是属于预订的默认课程。
    damean
        59
    damean  
       2016-08-22 19:49:00 +08:00
    @wy315700 虽然多了一个向量配置(固定密钥),但依然不是加密算法。本质上还是属于摘要算法。
    @fyibmsd 非对称加密。。。你脑洞太大了吧。。。公私钥分别是啥?
    iyaozhen
        60
    iyaozhen  
       2016-08-22 19:52:07 +08:00 via Android
    @jimzhong 真的可以破解。 md5 , sha1 什么的都是 hash(摘要)算法,是不可逆的,不是加密。

    有了彩虹表是不安全,所以密码不要设置为'123456'这种简单的密码。但程序上可以加盐,比如 md5(md5('123456') + 'abc')。当然盐也不能很简单。设置可以每个用户不同的盐。
    binbinyouliiii
        61
    binbinyouliiii  
    OP
       2016-08-22 19:52:08 +08:00
    @damean 大神,这么厉害,“ Java 这么简单”
    话说 v 友们都对 java 很排斥吗
    damean
        62
    damean  
       2016-08-22 19:56:36 +08:00
    @binbinyouliiii java 真算是简单的。
    但是“排斥”是什么鬼?你是怎么脑补出“排斥”的?“简单”==“排斥”?
    binbinyouliiii
        63
    binbinyouliiii  
    OP
       2016-08-22 20:00:35 +08:00
    @damean 不是,我之前再 v 站看过几篇帖子,很多人对 java 都以嘲笑的态度来说的
    maxsec
        64
    maxsec  
       2016-08-22 20:47:49 +08:00
    "0e31a" == 0
    "0e1ba" == 0

    "0e31a" =? "0e1ba"
    nvidiaAMD980X
        65
    nvidiaAMD980X  
       2016-08-22 21:58:28 +08:00 via Android
    直接上 SHA512
    ZE3kr
        66
    ZE3kr  
       2016-08-22 22:14:25 +08:00
    你说的应该是如何存储密码以达到验证用户登录,而不是密码加密

    最不安全的是密码存明文,一般情况下没事,但一旦数据库被拖库,然后所有用户的密码都被知道。

    所以使用正确的方式存储密码可以尽量减少上述情况带来的灾难。

    首先,不应该使用 SHA-0 ( md5 ), SHA-0 的位数太短,已经不安全, SHA-1 目前都被认为不足够安全了,所以应该使用 SHA-256 或更高位数的, SHA-512 感觉没必要。

    应该这样存储,用户一个表中,应该包含这两样,都要存储

    salt = rand() # 一个随机数,位数最好要长于 256 个比特
    password = hash( password + salt )

    这样在验证用户的时候,读取这两个字段验证:

    if( hash( password + salt ) == hash( input_password + salt ) ){
    // 登录成功
    }


    关于已知数据库后破解原密码难度(假设 hash 算法达到了 hash 算法应该达到的安全性):

    1 只存储 hash :

    直接使用当前算法的彩虹表,(几乎)可以破解所有用户的原密码

    2 存储加一样的盐的 hash :

    可以针对当前的盐重新生成彩虹表,然后就能破解所有用户的原密码,难度远大于前者

    3 存储一个随机的盐和加随机的盐的 hash :

    必须针对每个用户单独破解,破解难度所有用户原密码难度直升至(基本上)不可能,难度远大于前者
    ZE3kr
        67
    ZE3kr  
       2016-08-22 22:20:52 +08:00 via iPhone
    随手创个加密方式?不是不可以,但是绝对不要这样做!

    目前使用的加密方法都是经过大量的实际使用而确认这是个“好”的加密算法

    几乎没有人会随手创个“好”的加密方式,如果你学过密码学,一些加密函数的实现,那么就再也不会想要自己创加密方式了。
    bombless
        68
    bombless  
       2016-08-22 22:27:31 +08:00 via Android
    一般不用 md5 都用 sha 并加盐了,不开玩笑

    哈希算法未必能散列的很好,谨慎一点好
    edsgerlin
        69
    edsgerlin  
       2016-08-22 22:35:54 +08:00   2
    md5 都是什么年代的玩意儿了,也就在不重视用户信息安全的中国大陆开发者里头算是自以为比明文存储强一些的 Best Practice 。
    单纯的 hash function 就算是 SHA3-512 也不应该作为 KDF 使用,即使加 nonce as salt 也不安全,这应该是普通开发者应该有的常识。说什么 MD5 不够安全应该用 SHA 系列的也只是五十步笑百步而已。
    安全界现在的共识是在 GPGPU 时代连 PBKDF2 、 bcrypt 这种都不能视为安全的 KDF 。当前得到较广泛使用的 GPGPU-proof 的方案是 scrypt ,然而依然有 ASIC 可以搞它。
    目前最安全的方案应该是 Argon2 ,只是对它的 Cryptanalysis 还不够多,不建议在生产系统中用。
    简单的说:
    安全性&计算开销: Argon2 > scrypt > bcrypt > PBKDF2 > hash with salt > plain hash > plaintext
    没有历史包袱的新系统最低限度应该用 PBKDF2 , cost factor 还要设得尽量大些反 rainbow table 。如果能用 scrypt 尽量上 scrypt 。
    认为普通 hash function 就能当 KDF 用的都应该去补习一下密码学导论,而直接把用户明文密码存储入库的蠢货应该枪毙。
    /div>
    edsgerlin
        70
    edsgerlin  
       2016-08-22 22:40:38 +08:00
    楼上那些说应该用 SHA 系取代 MD5 来提高安全性的,如果用户密码不是随机生成的话,拖了库,常见的 12 位以内密码用 GPU 算分分钟出个 rainbow table 。
    假如用户密码都是用 LastPass 等生成的 48 字符以上的随机字符串的话用 hash function 做 KDF 倒是足够安全,然而现实并没有那么简单。
    如果你们真有心提高用户密码存储的安全系数还是去补补密码学基础吧……
    edsgerlin
        71
    edsgerlin  
       2016-08-22 22:42:55 +08:00
    有兴趣可以参考 OWASP 上的相关资料,码农在信息安全方面知道这些基本上是够用了。
    https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet
    https://www.owasp.org/index.php/Hashing_Java
    mingyun
        72
    mingyun  
       2016-08-22 22:52:57 +08:00
    bcypt+1
    mikicomo
        73
    mikicomo  
       2016-08-22 23:55:49 +08:00
    @damean 好多人只是吐槽 JAVA 的语法吧...其实呢...我觉得 JAVA7/8 很不错啊,没那么多值得吐槽的吧....可是 V2 是 pythoner 的社区, java 被吐槽两句也是正常嘛,毕竟和 python 比起来不简洁是真的....可是谁也不能排斥 java 不是, N 多大型系统都是 java 带起来的呐,你看 BAT 哪家不需要 java ,只是 java 年纪大了嘛,被吐槽是正常哒
    msg7086
        74
    msg7086  
       2016-08-23 08:18:29 +08:00
    @edsgerlin Overkill 了。无脚大楼可能会用那个级别,普通的网站真没必要。加了随机盐的 MD5 已经可以挡住普通破解者了,如果他们没有西湖之光的话。
    firebroo
        75
    firebroo  
       2016-08-23 08:21:30 +08:00 via Android
    如果为了保护用户密码 md5 加随机不固定长度 salt 足够安全了,至于两次 md5 自然是没有必要,仅仅只是让对方生成长虹表的时间*2 而已。 md5 最初的设计就不是用来加密的。自创算法是没有数学理论支撑,算法公开就完。
    Clarencep
        76
    Clarencep  
       2016-08-23 09:10:33 +08:00
    @ostholz @mingyun bcrypt -1

    用户的密码不应该使用 bcrypt 这样可以解密的加密方式 -- 除了用户之外的所有人都不应该知道用户的密码。
    用户密码的存放肯定以及必须使用单向加密的方式,也就是用 hash 算法,而不是用 bcrypt 这样的可以解密的加密方式。
    annielong
        77
    annielong  
       2016-08-23 10:00:12 +08:00
    对于一般网站,对 md5 进行简单的变形或者增减就够了,
    glasslion
        78
    glasslion  
       2016-08-23 10:07:26 +08:00
    @msg7086 bubcrypt 本来就是哈希算法
    kaneyuki
        79
    kaneyuki  
       2016-08-23 10:41:16 +08:00
    于是加盐的根本目的是把被加密数据变长,让彩虹表生成变得极为困难咯?
    edsgerlin
        80
    edsgerlin  
       2016-08-23 10:41:40 +08:00
    @msg7086 即使是随机盐,要知道大部分用户的密码都不是随机生成而是有一定规律的,比如日期、手机号、身份证号等以及一些拼音、英文单词的组合等,因此可以说 95%以上用户的密码的信息熵都可以说是达不到 48bit 以上的。如果针对特定用户进行 targeted attack ,用 CUDA 推算原密码是分分钟的事情。因此必须用比通用 hash function 计算开销高得多的 key derivation function 才能保障安全。

    @Clarencep 多看看书, bcrypt 不可逆,而且 bcrypt 是专用 KDF ,做密码变换比 MD5 之类的通用 hash 好多了。

    说二次 Hash 就很安全的也是 Naive ,要知道 PBKDF2 就是标准化的 N 次通用 hash 迭代。例如 Wi-Fi 加密常用的 WPA2-PSK 是用 4096 次 SHA1-HMAC 迭代来生成 256bit 的 AES 密钥, salt 用的是 SSID 。

    在不能确保用户使用信息熵足够多的密码的情况下采用单纯的 hash with nonce as salt 都是不安全的,而唯一能确保用户使用信息熵足够多的密码的方法是鼓励用户用 LastPass 、 KeePass 、 1Password 之类的密码管理器生成 48 字符以上随机字串做密码(单 ASCII 字符信息熵可以认为是 6bit 吧,这里假设要提供约 256bit 强度的信息熵),而且一站一密。这个条件明显比用 bcrypt 保护用户愚蠢的密码更不切实际。

    现代 KDF 的发展史就是提高计算复杂度(PBKDF2, bcrypt)->提高空间复杂度(scrypt)->提高 ASIC 实现复杂度(Argon2),一切都是为了保护用户愚蠢的低熵密码。
    edsgerlin
        81
    edsgerlin  
       2016-08-23 10:50:42 +08:00
    @kaneyuki 不加盐的话,比如用户用 HelloWorld1984 做密码,这种低熵密码如果没有盐的话直接 lookup 一下别人计算好的 rainbow table 就能知道原文了。如果有加盐的话就要根据已知盐+常见密码重新开始计算,相对来说没那么轻松。
    然而 GPU 计算时代算通用 hash function 的 rainbow table 而且覆盖常用密码空间并不是多难的事情,即使每个用户都加上随机盐也只是提高了大规模撞库的难度而已,不能反针对少量用户的 targeted attack 。
    真正要让 rainbow table 的生成更困难只能采用计算开销几万倍于通用 hash function 的专用 key derivation function ,比如 bcrypt 、 scrypt 之流。
    daemonghost
        82
    daemonghost  
       2016-08-23 11:49:54 +08:00
    @reyoung1110 md5 是 hash 算法,也可用于加密,在安全领域 md5 以前用得还是挺多的啊
    3dwelcome
        83
    3dwelcome  
       2016-08-23 12:13:21 +08:00 via Android
    @youxiachai 你老师没说错、 md5 也有加密用途、为了消耗 cpu 计算力的循环算法、只是用的少、很多人并不知道罢了。
    Clarencep
        84
    Clarencep  
       2016-08-23 12:19:04 +08:00
    @edsgerlin 好吧,我把 bcrypt 和 mcrypt 弄混了
    cjyang1128
        85
    cjyang1128  
       2016-08-23 13:03:07 +08:00
    bcrypt 大法好
    chaegumi
        86
    chaegumi  
       2016-08-23 13:18:20 +08:00
    其实我看还是因为 md5 是内置的,不用安装啥组件这个原因,上古遗留下来的
    SlipStupig
        87
    SlipStupig  
       2016-08-23 13:33:53 +08:00
    @3dwelcome 我可能学的不好,请问既然 md5 可以加密,怎么才能解密出来呢?
    SlipStupig
        88
    SlipStupig  
       2016-08-23 13:41:57 +08:00
    @iyaozhen 现在字典攻击只是一部分,更厉害是 GPU 集群破解, hack 拿一两千台机器的 gpu 去跑,一般的摘要算法几乎扛不住
    Asimov
        90
    Asimov  
       2016-08-23 14:18:51 +08:00
    @edsgerlin scrypt 也啥用啊,特多的是,破解他不是分分的事。
    mnzlichunyu
        91
    mnzlichunyu  
       2016-08-23 14:50:25 +08:00
    一个加密算法应该是默认攻击者知道加密算法,还能保证安全性的。自己随手搞一个加密算法,应该是很难保证这一点;
    md5 不是加密算法;
    3dwelcome
        92
    3dwelcome  
       2016-08-23 14:55:04 +08:00 via Android
    @SlipStupig 加密又不需要解出来、能防止被暴力破解就可以了啊、你一个 gpu 破一遍 md5 没压力、但是递归几千次几万次呢?把算法复杂到足够强、就如比特币解算的强度、一般黑客还真破不了。

    再说 md5 加密又不是谁一拍脑袋想出来的、是 freebsd unix 最初用户系统安全的基础算法。
    3dwelcome
        93
    3dwelcome  
       2016-08-23 14:57:29 +08:00 via Android
    Md5 本身是散列算法。但也有 md5 加密算法、已经修改了 md5 一次计算的本质、两者代码差很多、别搞混了。
    3dwelcome
        94
    3dwelcome  
       2016-08-23 15:03:14 +08:00 via Android
    那些以为算一次 md5 就是加密的同学可以洗洗睡了、完全不是这样的流程。
    SlipStupig
        95
    SlipStupig  
       2016-08-23 15:21:12 +08:00
    @3dwelcome 加密解密不出来有什么用,我自己随便写一个随机数也算加密算法?
    3dwelcome
        96
    3dwelcome  
       2016-08-23 16:34:38 +08:00
    @SlipStupig MD5 没加密,会被黑客有针对性的攻击。而把算法修改后,黑客就没办法轻易攻击了,这流程肯定是叫加密啊。

    人家老外从一开始就叫 MD5 加密,要不然谁会跟着叫这个。咬文嚼字就没意思了,你一定说这是 MD5 混淆算法,那我也没办法。
    https://www.usenix.org/legacy/events/usenix99/provos/provos_html/node10.html
    edsgerlin
        97
    edsgerlin  
       2016-08-23 17:26:20 +08:00
    @Asimov 一样用了 ASIC 的情况下计算 scrypt 依然比 md5 之流消耗多得多的资源,况且 MD5 这种都不用 ASIC ,直接 GPU 就能算了。防矿机目前推荐 Argon2 ,虽然太新了点。
    note286
        98
    note286  
       2016-08-23 17:42:06 +08:00
    不要自己创造加密算法, 而且 MD5 也不是加密算法, 因为它不需要密钥, 他是散列函数, 你不是专业的密码学专家, 不要试图去自己编一个算法, 你以为看着不错, 其实专家你看就觉得弱爆了, 好的算法需要经过数学上的测试和时间的检验, 大概就是这样, MD5 长度有点短, 所以彩虹表有点优势, 我们可以使用 SHA-256 啊, 这个是很长的, 而且你不要直接散列啊, 你加盐啊, 用户可能会起 123456 这样的弱密码, 123456 对应的哈希值大家都知道, 但是你可以加盐啊, 这样就没人知道用户的密码是 123456 啊, 你说是吧.
    fjzjk
        99
    fjzjk  
       2016-08-23 17:45:04 +08:00
    我之前也是这么想的。后来老手说:你可以 md5 加密两次...........
    md5 实际上是不算加密的,用他大概只是因为方便而已。
    asdwfwqd
        100
    asdwfwqd  
       2016-08-23 18:01:26 +08:00
    好像听谁说过:很多程序员用 md5 的原因是,教科书里面举例子就是用的 md5 ,虽然 md5 不适合用来加密
    1  2  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2768 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 07:34 PVG 15:34 LAX 23:34 JFK 02:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86