MD5结果的缩短

网络上的代码一般使用substr(md5("x"),0,16)、substr(md5("x"),8,16)、substr(md5("x"),8,-8)这种有损的的方式截取长度(最好用array_unique()剔除重复,即便如此如果多次生成也可能存在重复),md5("x",true)说是长度为16又都没写清楚,这里稍作研究。

  • md5()产生128位内容。
  • 默认使用16进制(16进制即二进制1111[4位],十进制为15加1进1)分成【32】组4位,长度为32的字符串,每个字符为[0-9,a-f]总共15个字符表示。
  • md5("x",true)输出128位二进制,直接打印的话根据不同编码(8位一字符长度就为16)可能产生乱码。
  • 因此如果我使用大的进制来表示md5()结果的话,将会更短。
  • 试验代码:
<?php
//md5()产生128位内容。
//默认使用16进制(16进制即二进制1111[4位],十进制为15 加1进1)分成【32】组4位,长度为32的字符串,每个字符为[0-9,a-f]总共15个字符表示。
//因此如果我使用大的进制来表示md5()结果的话,将会更短。
//md5("x",true)输出128位二进制,直接打印的话根据不同编码可能产生乱码。

$data='';
$i=0;
//这里转换成二进制内容的字符串。为什么不使用md5("x",true)生成128位二进制?php没现成的二进制分割连接工具。
foreach(str_split(md5("x")) as $item){
    $d=str_pad(base_convert($item,16,2), 4, "0", STR_PAD_LEFT);//16进制转2进制并补0
    $data.=$d;
    $i++;
    echo "{$i}-{$d}\n";//2进制结果
}
echo "\n";

echo strlen($data);echo "\n";//128位二进制结果


$data.="00";
$j=0;
//使用32进制(32进制即二进制11111[5位] || 十进制为15 加1进1)分成【26】组5位(=130位,前面加两个00以便整除),每个字符为[0-9,a-v]总共31个字符表示
foreach(str_split($data,5) as $item){
    $j++;
    echo $j.'-'.base_convert($item,2,32);//32进制结果
    echo "\n";
}
echo "\n";
//结果成功缩短成长度为26的字符串,值不变
//可以使用更大进制么?可以,但base_convert()最高只支持36进制,需要自己实现更高进制转换。
//那为什么不使用36进制?因为十进制35 = 二进制100011,如果结果中刚好有一个111111~100111的值 > v,转换后将产生两个字符,最终长短不统一。同理33-35进制
?>
  • 思考
    如果使用足够大的进制就可以任意缩短;
    用更好的字符表示,每种进制结果其实是由进制数-1个字符表示,自己就可以组织并剔除一些容易混淆的字符比如数字1和小写的l,数字0和字母o,相当创造自己的进制的表示方法,当然不管从哪方面讲,使用扩展来做是最好的方法;
    这也是一种改进的加密方式。

标签: none

仅有一条评论

  1. The time to read or go to the subject material or web-sites we have linked to below.

添加新评论