PHP MD5加密解密原理详解

一、什么是MD5加密?

MD5加密是一种单向加密算法,将任意长度的数据加密成固定长度的密文。主要被用于密码加密,数字签名等领域。

MD5加密特点:

1、加密结果是固定长度的128bit字符串,不管加密前数据的长度多长,密文长度始终为128bit。

2、同样的数据进行MD5加密后,生成的密文总是相同的。

3、密文经MD5加密后无法通过任何手段还原为明文。

二、MD5加密的实现原理

MD5加密通过对明文进行多次处理,生成固定长度的密文。处理过程主要包括以下几步:

1、填充

将明文进行长度扩展,使其长度满足448mod512,并在其末尾添加一个64bit的数据,用于保存明文本身的长度。


//填充函数
function padding($str){
    $len = strlen($str);        //得到字符串长度
    $pad_len = 448 - $len % 512;    //计算需要填充的长度
    if($pad_len <= 64)   //如果需要填充的长度介于1-64之间,则需要加一个分组
        $pad_len += 512;
    $pad_char = chr($pad_len/8);    //计算需要填充的字符
    $padding_str = "";
    for($i=0; $i<$pad_len/8; $i++)  
        $padding_str .= $pad_char;
    $padding_str .= $str.pack("Q*", $len*8);    //连接原始数据长度
    return $padding_str;  
} 

2、初始化

对填充后的明文进行初始化,生成4个32bit的缓存区,对应a、b、c、d。根据RFC1321规格定义的初始值,将a、b、c、d设置成如下值:

a = 0x67452301

b = 0xEFCDAB89

c= 0x98BADCFE

d=0x10325476


//初始化MD5状态变量
$A = 0x67452301;
$B = 0xEFCDAB89;
$C = 0x98BADCFE;
$D = 0x10325476; 

3、四轮迭代

将初始化后的缓存区与每个512位的分组进行四轮迭代计算,每轮迭代对缓存区进行ABCD四个变量的置换。


//四轮迭代
function md5_loop($f, $m, $s, $i){
    global $A, $B, $C, $D;
    if($f == 'F')
        $res = ($B & $C) | (~$B & $D);
    else if($f == 'G')
        $res = ($B & $D) | ($C & ~$D);
    else if($f == 'H')
        $res = ($B ^ $C ^ $D);
    else if($f == 'I')
        $res = ($C ^ ($B | ~$D));
    $temp = $B + shiftleft(($A + $res + $m + $s[$i]), $i*5%32);
    $A = $D;
    $D = $C;
    $C = $B;
    $B = $temp;
}

//用于循环左移
function shiftleft($num, $bits){
    $num = $num & 0xffffffff;    //强制截断为32位
    $num_str = decbin($num);    //转换为二进制字符串
    $num_str = str_pad($num_str, 32, 0, STR_PAD_LEFT);    //补充0,使其长度变成32位
    $num_str = substr($num_str, $bits).substr($num_str, 0, $bits);    //将字符串分为两部分,分别进行循环左移
    return bindec($num_str);    //将处理结果返回为十进制数
}

4、生成密文

经过四轮迭代之后,将四个缓存区连接起来,组成128bit长度的MD5摘要,即为密文。


//生成MD5摘要
function md5($str){
    $padding_str = padding($str); 
    $chunk = strlen($padding_str) / 64;    //分段
    for($i=0; $i<$chunk; $i++){
        $str_chunk = substr($padding_str, $i*64, 64);    //得到每一段字符串
        $word = array();
        for($j=0; $j<16; $j++){
            $word[] = unpack("V", substr($str_chunk, $j*4, 4))[1];    //将字符串分为16组,每组4个字节,然后将每组转换成unsigned int数值
        }
        //四轮迭代
        $s = array(7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21);
        $K = array(0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,    0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391);
        for($j=0; $j<64; $j++){
            if($j<16){
                md5_loop('F', $word[$j], $s, $j);
            }
            else if($j<32){
                md5_loop('G', $word[(5*$j+1)%16], $s, $j);
            }
            else if($j<48){
                md5_loop('H', $word[(3*$j+5)%16], $s, $j);
            }
            else{
                md5_loop('I', $word[(7*$j)%16], $s, $j);
            }
        }
    }
    $md5_str = pack("V4", $A, $B, $C, $D);    //将4个缓存区合并成字符串
    return bin2hex($md5_str);    //将字符串转换成16进制数值
}

三、MD5解密

MD5加密是一种单向加密算法,无法通过密文还原明文。但是可以通过穷举法,对所有可能的明文进行加密,找到和密文一致的密文,即为原来的明文。


//MD5解密
function md5_decrypt($str, $target_md5_str){
$padding_str = padding($str);
$chunk = strlen($padding_str) / 64;
for($i=0; $i<$chunk; $i++){
$str_chunk = substr($padding_str, $i*64, 64); //得到每一段字符串
$word = array();
for($j=0; $j<16; $j++){
$word[] = unpack("V", substr($str_chunk, $j*4, 4))[1]; //将字符串分为16组,每组4个字节,然后将每组转换成unsigned int数值
}
//四轮迭代
$s = array(7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21);
$K = array(0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd

原创文章,作者:DTTI,如若转载,请注明出处:https://www.506064.com/n/143090.html

(0)
DTTIDTTI
上一篇 2024-10-14
下一篇 2024-10-14

相关推荐

  • TCP端口详解

    一、tcpport指令 tcpport指令是探知TCP端口状态的重要工具之一。使用tcpport指令,在调试TCP协议时可以查询自己服务器上开放的端口有哪些;在进行安全审计时,可以…

    编程 2024-10-14
  • c语言判断字母还是数字,c语言判断字母和数字

    本文目录一览: 1、C语言程序中如何区分字符是数字还是字母 2、C语言:如何判断输入的是数字还是其他字符 3、C语言程序中,如何区分字符是数字还是字母? 4、c语言中如何判断输入的…

    编程 2024-10-04
  • Java StringBuffer的用法

    1、引入 在Java中,字符串是一个非常基础的数据类型,它有时会产生大量的对象,这会影响Java应用程序的性能。而StringBuffer类是Java提供的一个字符串处理类,它可以…

    编程 2024-10-03
  • python常用编程实例的简单介绍

    本文目录一览: 1、初学者学习python编程要掌握什么内容? 2、python编程实例——求满足条件的三位数 3、用python编程 4、学完Python都可以做什么 5、pyt…

    编程 2024-10-04
  • CSSID的详细解析

    一、CSS四大 CSS是指层叠样式表,是前端开发中必不可少的一部分。CSS四大是指盒模型、定位、浮动和清除浮动。 在网页排版中,盒模型是最基础的一个概念,用于确定元素的尺寸和边距。…

    编程 2024-10-04
  • js编程怎么写,js如何写

    本文目录一览: 1、js怎么写啊 2、JS代码怎么写 3、怎么编写和调用js文件 js怎么写啊 1 打开dw软件,新建一个文档,然后输入一些代码,代码如下:script type=…

    编程 2024-10-14
  • 并将结果写入mysql数据库(mysql数据文件入库)

    本文目录一览: 1、如何将这个PHP的结果保存到mysql数据库。 2、如何将hive的结果写入mysql 3、Hadoop MapReduce中把分析数据写入mysql中 4、如…

    编程 2024-10-03
  • php只比较两个日期,php两个日期差几天

    本文目录一览: 1、php实现比较两个字符串日期大小的方法 2、用php计算两个日期相差多少 3、php 代码 怎么比较日期大小 4、Php有没有办法比较两个时间的年月日是否相等 …

    编程 2024-10-04
  • java时间格式,java时间格式校验

    本文目录一览: 1、java怎么把日期时间(2018-01-12 00:00:00)转化成(2018-01-12 00:00:00.000+0800)这种格式 2、用java获取日…

    编程 2024-10-03
  • c语言基本数据类型实验分析,c语言基本数据类型实验报告

    本文目录一览: 1、C语言的基本数据类型和举例! 2、C语言的三种基本数据类型是什么? 3、C语言实验二 数据类型、运算符与表达式 与顺序表达式 4、C语言 四种基本数据类型 5、…

    编程 2024-10-04

发表回复

登录后才能评论