diffnest / myblog

0 stars 0 forks source link

项目中用到的异或加密算法(PHP) #5

Open diffnest opened 7 years ago

diffnest commented 7 years ago

对接交易所接口,用到了异或加密算法,心想这么大的交易所,居然用异或加密,不怕给破解了么,不管了,先记录一下吧;

异或:异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。

如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

二进制中:

可以看出若两个数相同取0,不同取1
例:运算11001 ^ 01011 = 10010

如果用其他进制进行运算时,先将他们转化成二进制,再做运算(不足的位在前边填0补齐)
例:6 ^ 3 = 110 ^ 011 = 101

加解密过程:

  1. 参数说明

    • ciphertext:是将身份数据加密后产生的,其由以下数据组成
      (1)调用者ip
      (2)特定随机字符串:在express中抽取的部分片段
      (3)请求时间:请求时间的字符串,格式为”yyyyMMddHHmmss”,
      如201705161452 每个部分之间用字符”-”隔开。
      如:192.168.0.1-T3Qfh-20170608113839

    • express:是用来解析ciphertext的随机字符串express,其由以下两个部分组成:
      2.1 随机字符串:随机的20位字符串,在其中抽取出成为ciphertext特定随机字符串的部分。
      2.2 随机数:1-16的随机数。

  2. 加密过程

    • 随机生成一个 20 位的随机字符串和一个 1-16 的随机数,拼装成为 express。
    • 根据随机数在随机字符串中抽取相应位置为起始位置的 5 位随机数作为 ciphertext 中的随 机段。
    • 将 ip、随机段、调用时间以字符”-”进行分割并按照所述顺序拼合成为明文。
    • 将明文变为 ascii 码,并且每段 ascii 码都和第一步生成的随机数进行异或操作,并且以字 符”-”进行分割。
  3. 解密说明

    • 得到 ciphertext 密文和 express 时,首先解析 express 获得随机数和随机字符段;
    • 然后将 ciphertext 密文中 ascii 码分开并与随机数进行异或运算后,解析为明文获得 ip、随机字 符段和调用时间,并判断 ip 是否为事先定好的 ip 值、随机字段是否与 express 中解析的一致
  4. 示例说明

    • 随机字符串:FNQQFT3QfhgKRcMThpk
    • 随机数:6
    • express 值:FNQQFT3QfhgKRcMThpkF6
    • ip 地址:192.168.0.1
    • 时间:20170608113839
    • 截选的字符串:T3Qfh
    • 明文字符串:192.168.0.1-T3Qfh-20170608113839
    • getByte 后:495750464954564648464945845181102104455048495548544856494951565157
    • 密文:33-34-35-62-37-39-62-33-40-32-62-37-36-61-70-40-101-34-117-61-34-32-33-39-32-38-35-32-33-38-34-34-32-38-
  5. C代码 示例:

    #include <stdio.h>
    main()
    {
       char a[]="Password";        //要加密的密码
       char b[]="encryption";     //密钥
       int i;
    
       //加密代码
       for(i=0;a[i];i++)
            a[i]=a[i]^b[i];
            printf("Your Password is encrypted: %s\n",a);
    
       /*解密代码*/
       for(i=0;a[i];i++)
            a[i]=a[i]^b[i];
            printf("You Password: %s\n",a);
    }
    
    PHP实例代码
    
    $express = 'U9rmosZvZcStF5wV8u2e16';
    $ciphertext = '33-34-35-62-37-39-62-33-40-32-62-37-36-61-70-40-101-34-117-61-34-32-33-39-32-38-35-32-33-38-34-34-32-38-';
    
    function verifyDecrypt($express, $ciphertext)
    {
        $xorObj = new XOR();
        $newString = (string) $xorObj->decrypt($express, $ciphertext);
    
        print_r($newString);
        exit;
        list($ipAddress, $randString, $date) = explode('-', $newString);
        if ($ipAddress != '123.57.180.54') {
            $this->errorMsg('ERROR : IP NOT EXIST');
            return false;
        }
        return true;
    }
    调用得到:123.57.180.54-V8u2e-20170630162206
    
    具体解密代码:
    class XOR {
        public function xordecrypt($str, $key)
        {
            $slen = strlen($str);
            $klen = strlen($key);
            for ($i=0; $i < $slen; $i = $i + $klen) {
                $string = substr($str, $i, $klen );
                $xorString .= $key ^ $string;
            }
            return $xorString ? $xorString : '';
        }
    
        public function decrypt($express, $ciphertext)
        {
            $express = str_replace("'", "", $express);
            $expressNum = substr($express, 20, 2);
    
            $ciphertext = str_replace("'", "", $ciphertext);
            $ciphertextArr = explode('-', $ciphertext);
            foreach ($ciphertextArr as $cipher) {
                if (!$cipher) {
                    break;
                }
                //异或运算
                $xordecryptString = $this->xordecrypt($expressNum, intval($cipher));
                //ASCII转字符串
                $newString .= chr($xordecryptString);
            }
            return $newString;
        }
    }