使用MD5来加密数据的安全隐患?

2012-01-15 12:51:18 +08:00
 Semidio
MD5本来就不是一个加密算法,它是用于确保信息传输完整一致的算法。
先不提碰撞的问题,虽然MD5的编码会使原文变成不可逆的Hash编码,但这是在原文长度无限制的情况下,如果原文长度有限,例如密码(一般不超过16位),那么一个MD5编码就可以对应到有限多个原文,而且长度越短,可以对应到的原文越少。
而且还可以通过事先计算好对应码表,之后只需对照即可。即使使用(原文+固定值)再MD5,只要新建多个账号,查看其保存的MD5值,很容易就可以找到规律,获得这个固定值的数值,从而破解密码的加密。
使用随机值的话,也只要新建更多的账号,根据原文密码和MD5解开后的数值对照,总可以找到其内在随机规律,从而破解加密。
按照现在的电脑运行速度,这些运算应当都不是什么负担了。
是不是以后用MD5加密的数据都不安全了呢?
5818 次点击
所在节点    问与答
17 条回复
GordianZ
2012-01-15 12:57:37 +08:00
加随机salt是必要的~
Semidio
2012-01-15 13:07:24 +08:00
@GordianZ 随机salt只要花时间一样可以破解的出来啊
skydark
2012-01-15 14:03:15 +08:00
黑客通常不是对一个人而是对同一个库中的一批人感兴趣。如使用固定salt,黑客不得不针对该站构造一张单独的彩虹表。如使用随机salt,黑客不得不对每个用户构造单独的彩虹表。
通常前者在该站有相当价值的情况下是值得的,后者往往入不敷出。破解大多数情况下总是可以的,让破解的成本远大于收益即可。
Ryans
2012-01-15 14:09:14 +08:00
正如你文中第一句,MD5 本意就不是用来加密的。
est
2012-01-15 14:58:16 +08:00
> 例如密码(一般不超过16位),那么一个MD5编码就可以对应到有限多个原文

没看懂这句话。LZ确定你在说散列?
Hyperion
2012-01-15 16:14:11 +08:00
@Semidio orz, 我们来算一下...

密码如果由大小写+数字组成, 一共 (26*2+10)= 62个元素.

16位密码, 一共就有 (62^16)= 47672401706823533450263330816种组合.

加一截salt, 每加一位, 就是把幂加了个1.


找到salt规律? 找吧, 如果掺一段长度20的salt, 那就必须得穷举 3.35815565×10^64 次才能算出来(最坏情况), 就算动用量子计算机这种神器, 也起码得花上很一段时间, 但这不蛋疼么?

话说回来, 如果把salt当作密钥, 只要用简单的加密算法处理一下的话 -_,-
Hyperion
2012-01-15 16:15:37 +08:00
"加一截salt, 每加一位, 就是把幂加了个1. " => "加一截salt, 每加一位, 就是把指数加了个1. "
yyfearth
2012-01-15 16:40:05 +08:00
@Semidio md5单纯这个算法确实有些过时,sha1稍微好些,建议使用更加高级的sha256甚至sha512.一方面更加安全,另一方面长度也更长。保存字符串时建议用binary或base64而不是hex,这样就算sha512也很短。原因是,md5和sha1已经可以“碰撞”,不需要找出原来的数据效果相同。
另外,加salt是必须的。如果加固定的salt,那么通用的彩虹表失效,但是依然可以针对你生成一个彩虹表。加动态的salt,这样彩虹表基本上就费了,因为这样要对每一个salt(就是每个用户)生成一个彩虹表,这样顶多只能对少量用户进行攻击,而且意义不大,不如直接穷举。
这样安全性就足够了,对于你的几个观点,我不太同意:
1“即使使用(原文+固定值)再MD5,只要新建多个账号,查看其保存的MD5值,很容易就可以找到规律,获得这个固定值的数值”,如果你的“固定值”足够长(比如1024bit),你根本不可能找出这个“固定值”,除非看到源码。
2“随机salt只要花时间一样可以破解的出来啊”这个是爆破(字典穷举),加salt只能防彩虹表,对于爆破意义不大。
任何的加密,只有有足够的时间,一定可以得到,问题是这样,密码的实效已过,破解变得无意义,另外这样的投入远大于产出,黑客不会这么傻。
yyfearth
2012-01-15 16:42:46 +08:00
@Ryans “用户密码”是不用所谓的“加密”的,因为密码原码本身不需要存储(对于隐私考虑,也不应该存储),因此你只要验证他“是否一致”不就可以了啊。这样用这些hash,是没有太大问题的,只是要考虑强度问题。
hq5261984
2012-01-15 23:10:04 +08:00
@Semidio 如果真按LZ说的那么简单,王晓云的院士就应该给LZ了。不过LZ说的一个观点是对的,任何密码只有给足够的时间就能被破解即伯格夫斯基定律。但是时间本身在密码学领域里就是一个成本,任何密码只有在有效时间内被破解才能称为成功破解。实际上采用LZ所说的暴力破解的方法,时间长短并不取决于加密算法的优越性,更大程度上取决于密码的长度,如果密码为1位,在牛B的加密算法也会在短时间内被暴力破解。
@yyfearth
为防止碰撞,现在稍微有点安全需求的数据都是采用变换算法MD5.以PHP为例,我见过的大概有5种。

变换一:循环MD5

  最容易理解的变换就是对一个密码进行多次的MD5运算。自定义一个函数,它接受$data和$times两个形参,第一个是要加密的密码,第二个是重复加密的次数。

变换二:密文分割MD5

  尽管用户的密码是不确定的字符串,但是只要经过一次MD5运算后,就会得到一个由32个字符组成的字符串,这时可以再针对这个定长字符串变换。有点BT的算法是,把这段密文分割成若干段,对每段都进行一次MD5运算,然后把这堆密文连成一个超长的字符串,最后再进行一次MD5运算,得到仍然是长度为32位的密文。

变换三:附加字符串干涉
  在加密过程的一个步骤中,附加一个内容确定的字符串(比如说用户名),干涉被加密的数据。不可以用随机字串,因为这样会使原算法无法重现。这种算法在某些情况下是很具有优势的,比如说用于大量的用户密码加密,可以把用户名作为附加干涉字串,这样攻击者就算知道你的算法,也很难从他们手中的字典中一下子生成海量的对照表,然后大量地破译用户密码,只能有针对性的穷举为数不多的用户。

变换四:大小写变换干涉
  由于PHP所提供的md5()函数返回的密文中的英文字母全部都是小写的,因此我们可以把它们全部转为大写,然后再进行一次MD5运算。

变换五:字符串次序干涉
  把MD5运算后的密文字符串的顺序调转后,再进行一次MD5运算。

还有更BT的采用5种混合玩法,但是服务器开销很大。只能用BT来形容。
Hyperion
2012-01-15 23:46:50 +08:00
@hq5261984 曾经见过把原文用RC4先跑一遍, 然后送去MD5的. 速度快, 效率高.
yyfearth
2012-01-16 11:07:49 +08:00
@hq5261984 随机的salt可以分开或者合并保存。而且仅仅在数据库的时候使用。
比如 hash=sha(password+salt)+salt,在验证的时候,则要把这个salt取出来,进行校验。
这样,即使db被盗,彩虹表也没有用,只能针对某个用户单独建表就划不来了。
用username可以作为这个salt的一部分,不过由于username长度不是很长,而且不够随机,而且在db没有泄露的时候就已经已知了。
如果是客户端hash,就不能随机salt,除非吧salt也传过去(可以用timestamp,然后校验2者)
服务器端用于持久化,就可以考虑加入随机salt,可以吧这个salt存为一独立字段,或者像上面一样,合并在一起。
Hyperion
2012-01-17 13:35:30 +08:00
@yyfearth 其实只要salt够长, 暴露出来也没什么的吧? 如果安全性要求需要, 可以在客户端计算hash的时候加进一次性的salt, salt由服务端生成.
Hyperion
2012-01-17 13:42:33 +08:00
@yyfearth 啊, 一次性salt的方案有很大漏洞, 设想的不对... orz 没想清楚就发出来了
yyfearth
2012-01-17 13:53:14 +08:00
@Hyperion 一次性salt,不管再怎么长,如果泄露出来的话,只要针对性的建立一次彩虹表,就ok了。当然,不泄露的话,salt长点问题也不大。
对于salt的时候,分2个情况,一个是存储密码的时候,一个是校验密码的时候。2个时候可以采用不同的策略。
est
2012-01-17 13:57:00 +08:00
> 只要新建多个账号,查看其保存的MD5值,很容易就可以找到规律,获得这个固定值的数值,从而破解密码的加密。

这句话也太牛了。
Hyperion
2012-01-17 14:23:05 +08:00
@yyfearth 嗯, 戳下发送的一瞬间突然反应过来了...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/25645

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX