MAC校验

    这两天在改写一段java MAC校验代码为php类型的,之前也没接触过php,所以说中间出现了好多问题,这里保存一下代码:

首先用到的工具包:

<?php

function strToHex($string) {
    $string = mb_convert_encoding($string, 'ASCII','UTF-8');
    $hex = "";
    for ($i = 0; $i < strlen($string); $i++)
        $hex .= dechex(ord($string[$i]));
    $hex = strtoupper($hex);
    return $hex;
}

function hexToStr($hex) {
    $string = "";
    for ($i = 0; $i < strlen($hex) - 1; $i += 2)
        $string .= chr(hexdec($hex[$i] .
        $hex[$i +1]));
    return $string;
}

function SingleDecToHex($dec) {
    $tmp = "";
    $dec = $dec % 16;
    if ($dec < 10)
        return $tmp . $dec;
    $arr = array (
        "A",
        "B",
        "C",
        "D",
        "E",
        "F"
    );
    return $tmp . $arr[$dec -10];
}

function SingleHexToDec($hex) {
    $v = ord($hex);
    if (47 < $v & $v < 58)
        return $v -48;
    if (96 < $v & $v < 103)
        return $v -87;
}

function SetToHexString($str) {
    if (!$str)
        return false;
    $tmp = "";
    for ($i = 0; $i < strlen($str); $i++) {
        $ord = ord($str[$i]);
        $tmp .= SingleDecToHex(($ord - $ord % 16) / 16);
        $tmp .= SingleDecToHex($ord % 16);
    }
    return $tmp;
}

function UnsetFromHexString($str) {
    if (!$str)
        return false;
    $tmp = "";
    for ($i = 0; $i < strlen($str); $i += 2) {
        $tmp .= chr(SingleHexToDec(substr($str, $i, 1)) * 16 + SingleHexToDec(substr($str, $i +1, 1)));
    }
    return $tmp;
}

des ECB模式的加解密代码:

mac校验代码:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<?php
include ('DES.php');
include ('Util.php');


class MAC919desUtil{
    
    function MAC($mackey,$data,$key){
        $des = new Crypt_DES();
        $des->setKey(hexToStr('3535353535353535'));
        $primaryKey =SetToHexString($des->decrypt(hexToStr($key)));//主密钥的明文
        $des->setKey(hexToStr($primaryKey));
        $mingkey = SetToHexString($des->decrypt(hexToStr($mackey))); //用主密钥的明文解密mackey得到mackey的明文
        $data =strToHex($data);//将数据转换成16进制
        //组后一组不足16补0
        $de="";
        $datas=$this->retData($data);// 将macdata 分数值,每组16位(8 byte())
        for($i=0;$i<count($datas);$i++){
            if($i==0){
                //第一次只做DES加密
                $des->setKey(hexToStr(substr($mingkey,0,16)));
                $de=SetToHexString($des->encrypt(hexToStr($datas[$i])));
                
                
                
            }else{
                    //用上一次 DES加密结果对第 i 组数据做异或
                    $de=$this->myXOR($de,$datas[$i]);
                    // 对异或后的数据做DES加密
                    $des->setKey(hexToStr(substr($mingkey,0,16)));
                    $de=SetToHexString($des->encrypt(hexToStr($de)));
                    

            }
        }
            // des 加密最终结果用mackey后16位解密
            $des->setKey(hexToStr(substr($mingkey,16)));
            $de =SetToHexString($des->decrypt(hexToStr($de)));

            // 解密后 再用mackey前16位加密
            $des->setKey(hexToStr(substr($mingkey,0,16)));
            $de = SetToHexString($des->encrypt(hexToStr($de)));
            return $de;

    }
    function retData($data){
        $len=0;
        if(strlen($data)%16==0){
           $len=strlen($data)/16;
        }else{
            $len=(strlen($data)/16)+1;
        }
        
        $datas=Array();
        
        for ($i = 0; $i <$len; $i++) {
            if (strlen($data)>= 16) {
                $datas[$i] = substr($data,0,16);
                $data = substr($data,16);
                
                
            } else {
                $datas[$i] = $this->moveRigZero($data, 16, "0");
                break;
            }
        }
        
        
        return $datas;
    }

    // 右补 0
    function moveRigZero($args,$len,$str) {
        if (strlen($args)<$len) {
            while (strlen($args)<$len) {
                $args.=$str;
            }
        }
    
        return $args;
    }

    /*
     * 数据异或
     */
    function myXOR($str1,$str2) {
        $hex = "";
        if (strlen($str1)!= strlen($str2)) {
            echo "异或数据长度不等";
        }
        for ($i = 0; $i < strlen($str1); $i++) {
            
            $hex.=SingleDecToHex(intval(substr($str1,$i,1),16)^(intval(substr($str2,$i,1),16)));
            
                
        }
        return strtoupper($hex);
    }
    
    

}


?>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<?php
include ('DES.php');
include ('Util.php');


class MAC919desUtil{
    
    function MAC($mackey,$data,$key){
        $des = new Crypt_DES();
        $des->setKey(hexToStr('3535353535353535'));
        $primaryKey =SetToHexString($des->decrypt(hexToStr($key)));//主密钥的明文
        $des->setKey(hexToStr($primaryKey));
        $mingkey = SetToHexString($des->decrypt(hexToStr($mackey))); //用主密钥的明文解密mackey得到mackey的明文
        $data =strToHex($data);//将数据转换成16进制
        //组后一组不足16补0
        $de="";
        $datas=$this->retData($data);// 将macdata 分数值,每组16位(8 byte())
        for($i=0;$i<count($datas);$i++){
            if($i==0){
                //第一次只做DES加密
                $des->setKey(hexToStr(substr($mingkey,0,16)));
                $de=SetToHexString($des->encrypt(hexToStr($datas[$i])));
                
                
                
            }else{
                    //用上一次 DES加密结果对第 i 组数据做异或
                    $de=$this->myXOR($de,$datas[$i]);
                    // 对异或后的数据做DES加密
                    $des->setKey(hexToStr(substr($mingkey,0,16)));
                    $de=SetToHexString($des->encrypt(hexToStr($de)));
                    

            }
        }
            // des 加密最终结果用mackey后16位解密
            $des->setKey(hexToStr(substr($mingkey,16)));
            $de =SetToHexString($des->decrypt(hexToStr($de)));

            // 解密后 再用mackey前16位加密
            $des->setKey(hexToStr(substr($mingkey,0,16)));
            $de = SetToHexString($des->encrypt(hexToStr($de)));
            return $de;

    }
    function retData($data){
        $len=0;
        if(strlen($data)%16==0){
           $len=strlen($data)/16;
        }else{
            $len=(strlen($data)/16)+1;
        }
        
        $datas=Array();
        
        for ($i = 0; $i <$len; $i++) {
            if (strlen($data)>= 16) {
                $datas[$i] = substr($data,0,16);
                $data = substr($data,16);
                
                
            } else {
                $datas[$i] = $this->moveRigZero($data, 16, "0");
                break;
            }
        }
        
        
        return $datas;
    }

    // 右补 0
    function moveRigZero($args,$len,$str) {
        if (strlen($args)<$len) {
            while (strlen($args)<$len) {
                $args.=$str;
            }
        }
    
        return $args;
    }

    /*
     * 数据异或
     */
    function myXOR($str1,$str2) {
        $hex = "";
        if (strlen($str1)!= strlen($str2)) {
            echo "异或数据长度不等";
        }
        for ($i = 0; $i < strlen($str1); $i++) {
            
            $hex.=SingleDecToHex(intval(substr($str1,$i,1),16)^(intval(substr($str2,$i,1),16)));
            
                
        }
        return strtoupper($hex);
    }
    
    

}


?>

好多问题,这里保存一下我的代码留着以后用

原文地址:https://www.cnblogs.com/zhangkaijia/p/2987375.html