起序:这要因为一道 Web
题说起,那是一个月黑风高的白天…
一、程序展示
话不多说,先展示一下使用
md5()
对ffifdyop
字符串加密之后,第二个参数为true|false
不同的结果:
<?php
highlight_file(__FILE__);
echo '<br >';
$str = "ffifdyop";
echo md5($str, true);
echo '<br >';
echo md5($str, false);
?>
二、函数解释
php 手册
中md5()
函数的表示:可以看出md5()
函数的第二个参数默认是false
(不区分大小写)。
md5( string $str[, bool $raw_output = FALSE] ) : string
当
$raw_output
为true|false
的含义:不是很好理解,就是返回的结果形式不同。
- $raw_output = FALSE:以 32 字符十六进制数字形式返回散列值;
- $raw_output = TRUE:以16字节长度的原始二进制格式返回。
三、乱码的由来
这个时候可能会有疑问,当
$raw_output = TRUE
输出的乱码是怎么来的呢?来,咱们解释一下。
- 使用
md5("ffifdyop", true)
加密之后,会得到32 位 16进制
的字符串,和$raw_output = FALSE
输出的结果一样:276f722736c95d99e921722cf9ed621c
,但是还没完; - 将
32 位 16进制
字符串按照两两为一组,分割成16 组 16进制
的字符串:27,6f,72,27,36,c9,5d,99,e9,21,72,2c,f9,ed,62,1c
; - 将每一组
16进制
的数值转换成为2进制
数值:
100111
,1101111
,1110010
,100111
,110110
,11001001
,1011101
,10011001
,11101001
,100001
,1110010
,101100
,11111001
,11101101
,1100010
,11100
; - 将每一组
2进制
数值转换成为10进制
数值:39,111,114,39,54,201,93,153,233,33,114,44,249,237,98,28
; - 最后和
ASCII 码表
进行对照可翻译出最终的原始二进制字符串。
四、解决方式
解决方式有下面两种,网上大多数文章只写出第二种解决方式,对第一种就说说。
- 对输出的
16字节长度的原始二进制
转化为16 进制
; md5()
函数加密之后的密文中,16 位密文
和32 位密文
的8 - 23 位
子字符串是一样的,所以我们就可以通过字符串截取
的方式:substr(md5($str), 8, 16)
。
substr()
函数解释:这里只介绍$start
和$length
都是正数的时候,当然也是可以为负数,这里不做细讲,可以看php 手册
。
# $string: 输入的字符串
# $start: 截取的起始位置,从 0 开始计算
# $length: 截取的长度
substr( string $string, int $start[, int $length] ) : string
1、第一种:转化
- 害,太忙了,先留着。
2、第二种:截取
这是在 站长之家 测试
md5
16 位 和 32 位的比较,可以看出这之间的异同。
用
PHP 代码
表示:
<?php
highlight_file(__FILE__);
echo '<br >';
$str = "ffifdyop";
function md5_16($str){
return substr(md5($str), 8, 16);
}
echo md5_16($str);
echo '<br >';
echo md5($str);
?>
如果对您有帮助,点个赞再走吧。