md5
用途
1.校验文件完整性
2.存储密码改为存储md5,就算得到md5也无法知道密码(但是单纯密码的话,还是存在固定md5,这个时候我们应该给md5加盐)
加盐:就是在密码后边随机加随机数,然后将随机数存储,每次输入密码后边再加上随机数填充计算MD5
3.无法破解原始数据,因为md5是不可逆的
特性
1.输入任意长度的信息,经过处理,输出为128位的信息(数字指纹)
2.从原数据计算出MD5值很容易(容易计算)
3.让密文中的每一位受明文中的许多位的影响;
4.就是将密文与密钥之间的统计关系变得尽可能复杂,使得对手即使获取了关于密文的一些统计特性,也无法推测密钥。有损加密的过程,根据128位的输出结果不可能反推出输入的信息(不可逆)
5.无论密钥或明文的任何细微变化都应当引起密文的剧烈改变。输入中的一位发生变化,HASH值中将有至少一半发生变化。想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的(强抗碰撞)
6.寻找任何的(M1,M2),使H(M1)=H(M2)在计算上不可行,防范生日攻击。
7.不同的输入得到的不同的结果(唯一性)
语法:
string md5($str,raw)
$str:需要计算的字符串
raw:指定十六进制或二进制输出格式
1.基础使用
用来计算md5
2.输出格式
2、输出格式
raw 参数控制输出的「格式」:
true :16个字符的「二进制格式」
false :(默认)32个字符的十六进制格式
如果你在项目中遇到MD5「加密结果不一致」的问题,可以观察两个加密结果的长度是否相同,比如一个结果是16位,而另一个结果是32位,这种情况就可以考虑更换输出格式来解决。
实例:
1 | var_dump(md5('hello', true)); |
md5绕过
科学计数法绕过
md5()遇到公式,会先进行运算,再对运算结果计算md5
由于0和任何数相乘都等于0,所以0e开头的任何数,其md5都是相同的
比如 md5(‘0e1234’),会先运算成 md5(0),再计算MD5值。
补充:
0e是科学计数法,大小写等价,即 0e 和 0E 的结果相同。
科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式。
格式为:aEb=a×10^b,即a乘以10的b次幂。
绕过思路1:遇到弱比较(md5(a)==md5(b))时,可以使用0e绕过,即将a和b赋值为0e开头的数
0e绕过还有一种变体,如果某个字符串是0e开头的,在比较时,php也会先把它计算为0,在参与比较。
绕过思路2:遇到弱比较(md5(a)==0),可以传入QNKCDZO等绕过
一些MD5值为0e开头的字符串:
1 | QNKCDZO => 0e830400451993494058024219903391 |
数组类型(数组绕过)
md5()不能处理数组,数组都会返回NULL,同时会报一个warning,不影响执行
绕过思路:遇到强比较(a===b)时,可以使用数组绕过。GET传参时,以 a[]=1&b[]=2
这种形式传递数组。
1 | $a = array(1,2,3); |
算数运算配合自动类型转换
md5()遇到算数符时,会先运算,再计算结果的md5值
所以,当字符串与数字类型运算时,会将字符串转换成数字类型再参与运算,最后计算运算结果的MD5值
数值类型
虽然 md5() 要求传入字符串,但传入整数或小数也不会报错;数字相同时,数值型和字符串的计算结果是相同的。
MD5值相等的字符串
1 | $Param1="\x4d\xc9\x68\xff\x0e\xe3\x5c\x20\x95\x72\xd4\x77\x7b\x72\x15\x87\xd3\x6f\xa7\xb2\x1b\xdc\x56\xb7\x4a\x3d\xc0\x78\x3e\x7b\x95\x18\xaf\xbf\xa2\x00\xa8\x28\x4b\xf3\x6e\x8e\x4b\x55\xb3\x5f\x42\x75\x93\xd8\x49\x67\x6d\xa0\xd1\x55\x5d\x83\x60\xfb\x5f\x07\xfe\xa2"; |
$a==md5($a)
0e215962017
的 MD5 值也是由 0e 开头,在 PHP 弱类型比较中相等