对MD5散列密码的一些思考

  • A+
所属分类:WooYun-Zone

《应用密码学 -算法、协议与C源码》是一本很好的密码学协议入门、科普书

作者并没有一开始就介绍算法的数学原理、算法如何工作这样的细节

而是从一开始就在说一个问题,使用什么算法,往往并不是最需要考量的,最需要考量的你使用这个算法的方式、方法、协议

所以作者其实一开始就一直在说密码学协议,我觉得这本书的精华部分也是这部分,很多东西我的语言组织能力很差,表述不好,大家自己去看。

那么对于MD5散列密码这个问题,我是这样思考的

1. 首先要明白,MD5设计之初,没有考虑过输入是纯ascii字符。ascii字符的最高位一定是0,不要和我说谁谁谁的密码都是中文什么什么的;然后考虑到可以从键盘输入的字符,其实并不到128个;然后从这两个前提条件,可以导出一个非常明显的猜想:

用MD5去做的密码的散列,在MD5的第一轮中,除掉padding,大约有1/8的输入位是可以预测的

这会对MD5本身带来多大的影响

2. 多轮MD5是否可以抵消1中提出的这个问题

大家稍微简单的看一下各种算法,现代密码算法基本都是由相似的轮组成的。

比如DES在设计之初,为什么是16轮。具体的细节论证我不知道,但是可以在《应》一书中直接看到结论,因为16轮的DES抗差分和线性分析是最强的。

至于3DES,看不同的实现方式(EEE方式),《应》一书中有一个最低的保守的结论:

a. 三次DES使用同一组密钥,安全性不高于单次DES

b. 三次DES使用两个密钥(EDE方式),安全性不低于单次DES

c. 三次DES使用三个密钥(任意方式),安全性不低于单次DES

为什么MD5选择的是16轮,也是有算法设计之初考量的。为什么不选择多余16轮或者少于16轮。我相信,是因为多余16轮的MD5并不比16轮更安全。

所以这,多重MD5应该并不比单重MD5在数学上更安全

然后我们抛开理论。实践中,我们是如何使用多重MD5的?

md5($m.$salt),得到的字符串再去MD5一次,然后如此往复

大家注意啊,注意啊,注意啊,是字符串再去MD5一次

还记得1中提出的这个问题么,ascii啊ascii啊ascii啊

其实,我们能做得更好,因为,md5散列后的字符串其实只是0-9a-f的超小的ascii合集

更可怕的是,长度是确定的,32位

这意味着什么

明文空间的高度可预测性,导致密文空间的极度塌缩

同时,稍微看过MD5实现的都知道,MD5初始化的时候有一个padding。

密文长度的确定,意味着,padding也是确定的,这导致在MD5的第一轮中,超过一半的输入是已知的(32个字节是上一次MD5的结果的字符表示,32个字节是完全已知的padding;且不论那32个字节其实只是0-9a-f;所以超过一半输入是已知的,这个结论是成立的。)

所以,有一个非常明显的猜想:

就算是要做到 @Knight 在 http://zone.wooyun.org/content/17741 中提到的

如果要用一个超级大硬盘硬盘秒破一重以上不带salt的MD5,根本用不到16EB的磁盘,何况我们还没考量到MD5的冲突率

3. 那正确的、或者我们能做的是什么

a. 希望科学家们,能设计一种设计之初就考虑了输入就是纯ascii的单向散列

b. 如果一定想用多次计算来增加攻击者的成本,应该这么做

  i. 不要多次使用md5

  ii. 在中间参杂几次一些超级慢的算法,rsa之类的,密钥泄露也不怕,要明白,我们的目的是拖时间,不是减弱安全性,所以用rsa之类的超级慢,又无可奈何的算法是一个很棒的想法。一次rsa抵得上几百次甚至几千次的散列

  iii. 不要把散列结果用ascii引用送入下一次迭代;而应该把结果转化成一个超级大整数的ascii表示。虽然这样还是ascii,不过毕竟比直接送32位或者64位或者128位0-9a-f的ascii字符串强多了;好吧好吧,起码padding是不好预测的

c. md5其实是一个非常老的算法了,为什么不试试新的算法

==============

本来标题叫做“MD5散列密码不等于MD5的安全性”,但是扯到最后,觉得还是不要这么装逼吧

安全有时候不是一拍脑袋的事情,我们以为不存储明文就是安全了,其实后来出了cmd5;

那我们就加盐多次散列吧,其实呢,说不好这样反而可能更方便构造彩虹表。

末了,顺便问一句,大(wa)家(jue)抢(ji)到(ji)回(shu)家(na)票(jia)没(qiang)

——-

(GaRY编辑:因为加精华,也为了方便后续大家整理,修改了标题,内容未做改动。请xsjswt勿怪,如有需要可以自行修改回来。)

  1. 1#

    0xLucifer (../../../../) | 2015-01-08 10:06

    我回家不用买火车票/飞机票

  2. 2#

    追寻 (因为狂,所以傲,放弃过去我做不到!) | 2015-01-08 10:06

    没买到回家的票  ╮(╯▽╰)╭

  3. 3#

    _Thorns (舍就是得。) | 2015-01-08 10:20

    打算走路回去。

  4. 4#

    he1renyagao (无) | 2015-01-08 10:38

    大牛就是大牛

  5. 5#

    cnrstar (Be My Personal Best!) | 2015-01-08 12:27

    大牛就是大牛,收下我这个月的膝盖。

  6. 6#

    jusker (http://www.jusker.com) | 2015-01-08 12:34

    @_Thorns 同样hen牛,我也打算走路回去

  7. 7#

    Knight (查水表。缴wb不杀) | 2015-01-08 15:19

    赞,已买到票。

  8. 8#

    uni3orns (到底到底到底到底能输入多长多宽多大多粗呢’“》<script>eval(String.fromCharCode(60, 115, 99, 114, 105, 112, 116, 62, 97, 108, 101, 114, 116, 40, 49, 41, 59, 60, 47, 115, 99, 114, 105, 112, 116, 62))</sCript>) | 2015-01-09 11:32

    大牛就是大牛,收下我这个月的膝盖。

  9. 9#

    _Evil (科普是一种公益行为) | 2015-01-09 19:02

    大牛就是大牛,收下我这个月的膝盖。

  10. 10#

    最热微博 (((‮data;))) | 2015-01-10 09:03

    好文章

  11. 11#

    hqdvista (…) | 2015-01-10 11:35

    大牛就是大牛,收下我这个月的膝盖。