本帖最后由 上海分校-小影 于 2018-10-26 13:58 编辑
PHP中MD5加密的安全隐患
传智播客上海校区 崔长春老师
一.MD5加密是否可靠 从理论上来说,两个任意不同的字符串经过MD5加密之后,都会得到两个不同的结果,从这点上来说,MD5在理论上是安全的。但是!两个不同的字符串如果在比较的过程中有问题而导致相等,那么应用MD5函数时就需要格外小心了,以下是笔者在开发过程中遇到的问题,可以作为PHP中使用MD5函数不甚可靠的例证,不过不能冤枉MD5,这其实是弱类型语言的隐式转换造成的,而MD5本身还是安全的。 二.MD5加密不可靠例证 我们在PHP7.0版本下(在低版本下问题更多,故选高版本做测试),针对不同的字符串进行加密,然后对其加密后的结果进行比较,他们会不会相等呢?且看一例: $a='s1091221200a'; $b='s878926199a'; var_dump(md5($a)==md5($b)); 打印的结果是true!你没有看错,他就是true!两个不同的字符串加密之后怎么相等了呢?我们来分析一下: md5($a)的结果是:"0e940624217856561557816327384675" md5($b)的结果是:"0e545993274517709034328855841020" 这两个字符串显然也是不同的,其实这类字符串有很多很多,但是他们共同点是都以0e开头,问题就来了,0e开头的字符串在PHP中用两个等号比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方都是0!为验证我们的说法,我们看如下代码: var_dump(‘0e9876’==’0e123456’);结果为true; var_dump('0'=='0e123456');结果为true; var_dump('0w888'=='0e123456');结果为false; var_dump('0w888'=='0m123456');结果为false; 后两个是false推翻了是字符串变成0的可能,前面两个true有力地论证了我们的想法。
三.如何解决这些隐患 以上这类现象如何避免?在PHP中,两个等号的比较可靠性并不严谨,哪怕是两个类型一样的东西!所以必须是三个等号。例如上面两个等号有问题,但是改成三个等号再比较: $a='s1091221200a'; $b='s878926199a'; var_dump(md5($a)===md5($b)); 得到的结果是false!与我们的预期一致。
|