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!与我们的预期一致。