zoukankan      html  css  js  c++  java
  • php一步一步实现mysql协议(三) ——登录认证密码加密

    登陆认证阶段

    认证阶段抓包如上图,和初始化握手一样,前四个字节属于消息头,后面的部分属于消息体 。报文的结构图如下:

    这里主要设置 用户名 密码 和数据库名这三个参数,其他的使用抓包的默认值即可。用户名和数据库名直接将字符转为十六进制就可以,唯一需要注意的是密码加密部分

    官网提供的加密规则如下

    SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )

    实现代码如下:

    <?php
    function encryptionPass($pass, $seed)
    {
        $pass1 = getBytes(sha1($pass, true));
        $pass2 = sha1(getString($pass1), true);
        $pass3 = getBytes(sha1(hexToStr($seed) . $pass2, true));
        $result = "";
        for ($i = 0, $count = count($pass3); $i < $count; ++$i) {
            $result .= str_pad(dechex(($pass3[$i] ^ $pass1[$i])),2,0,STR_PAD_LEFT);
        }
        return $result;
    }
    
    function getBytes($data)
    {
        $bytes = [];
        $count = strlen($data);
        for ($i = 0; $i < $count; ++$i) {
            $byte = ord($data[$i]);
            $bytes[] = $byte;
        }
    
        return $bytes;
    }
    
    
    function getString(array $bytes)
    {
        return implode(array_map('chr', $bytes));
    }
    
    function hexToStr($hex_str){
        $send_msg = "";
        foreach (str_split($hex_str,2) as $key => $value) {
            $send_msg .= chr(hexdec($value));
        }
        return $send_msg;
    }

    我们从抓包记录中验证一下代码的正确性,在初始化握手包中获取两个salt的值 “1c171e1765783a57” 和 “50185b5a250f323d63394279”

    执行代码获取加密结果

    <?php
    $salt1 = "1c171e1765783a57";
    $salt2 = "50185b5a250f323d63394279";
    echo encryptionPass("123456",$salt1.$salt2);
    //生成结果:"a1b247e81adf52e0700e31698960ad96271b34f5"

    生成的结果与抓包获取的结果一致

    客户端向服务端发起认证请求后,服务端响应的情况分以下几种:

      当客户端发起认证请求或命令请求后,服务器会返回相应的执行结果给客户端。客户端在收到响应报文后,需要首先检查第1个字节的值,来区分响应报文的类型。

    响应报文类型第1个字节取值范围
    OK 响应报文 0x00
    Error 响应报文 0xFF
    Result Set 报文 0x01 - 0xFA
    Field 报文 0x01 - 0xFA
    Row Data 报文 0x01 - 0xFA
    EOF 报文 0xFE

      注:响应报文的第1个字节在不同类型中含义不同,比如在OK报文中,该字节并没有实际意义,值恒为0x00;而在Result Set报文中,该字节又是长度编码的二进制数据结构(Length Coded Binary)中的第1字节。

     代码分享地址

       https://github.com/gphper/PHPMysql

    参考文档:

      https://dev.mysql.com/doc/internals/en/client-server-protocol.html

      https://www.cnblogs.com/davygeek/p/5647175.html

      https://github.com/louislivi/SMProxy

  • 相关阅读:
    sublimetext3安装配置
    .Net Core 商城微服务项目系列(八):购物车
    .Net Core 商城微服务项目系列(七):使用消息队列(RabbitMQ)实现服务异步通信
    eShopOnContainers学习系列(三):RabbitMQ消息总线实践
    Docker系列(五):.Net Core实现k8s健康探测机制
    Docker系列(四):容器之间的网络通信
    Docker系列(三):将.Net Core Api部署到Kubernetes (K8s)中
    Docker系列(二):通过Docker安装使用 Kubernetes (K8s)
    生产环境项目问题记录系列(一):一次循环数据库拖垮服务器问题
    .Net Core 商城微服务项目系列(六):搭建自己的Nuget包服务器
  • 原文地址:https://www.cnblogs.com/itsuibi/p/13661538.html
Copyright © 2011-2022 走看看