php使用huawei md5 + 3des加密字符串

时间:2014-05-07 22:41:17

标签: java php security encryption 3des

哎 感谢提前阅读。

我在加密3des中的某些问题时遇到了一些问题,它正在运行,但似乎没有出现正确的值

目的: 我需要从PHP验证其他API,以便能够检索信息, 他们的文件说明了这一点:

  1. 步骤1调用登录函数接收令牌(我有这个)
  2. 步骤2,使用从令牌
  3. 生成的字符串调用authorize函数

    我已经实现了以下代码,但不确定是否做错了, 这里有来自文档的一些信息

    生成密钥的过程如下:
    1.华为定义的内部值99991231加入明文加密。结果A生成 2.在结果A上执行标准MD5算法。生成结果B. 3.结果B转换为十六进制数。结果C生成 如果十六进制字符串中的第一个字符为0,则忽略它。如果另一个字符为0,则保留它。例如,0x0100101F3B转换为100101F3B 4.获得结果C中的前八个字符。结果D生成 5.结果D中的字符将转换为小写字符。生成加密文本。

    这是他们提供的用于生成md5 huawei的示例代码(我认为它的java?需要它的PHP等价物)

    byte[] id = plainPwd.getBytes();
    
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(id);
    md.update("99991231".getBytes());           // “99991231” mentioned in XML-API DOC
    
    byte[] buffer = md.digest();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i <buffer.length; i++) {
        sb.append(Integer.toHexString((int) buffer[i] & 0xff));
    }
    String md5Pwd = sb.substring(0, 8);         // only use first 8 characters
    

    这就是所需要的:

    3DES加密算法用于生成验证器。要加密的纯文本格式如下: 随机+&#34; $&#34 + EncryToken +&#34; $&#34 +的userid +&#34; $&#34 + terminalid +&#34; $&#34 + terminalip + &#34; $&#34 + MAC +&#34; $&#34 +保留+&#34; $&#34; +&#34; CTC&#34;

    他们的密钥基于此生成:

      

    3DES加密结果转换为
    的十六进制字符串   ASCII模式,其中字母A到F是大写的。例如,如果是   3DES加密结果为0x0123456789ABCDEF,值为
      Authenticator是0123456789ABCDEF。生成的过程   验证者如下:
      1.客户端向EPG服务器发送订户认证请求。请求URL:http ... / XML / Authenticate
      UserID:10086Mac地址:ABCDEFGH
      2. EPG服务器返回enctytoken(例如,AD75B1697FB5EB6345B2D412124030D2)和encryptiontype(例如,   MD5)给客户。
      3.客户端使用MD5算法加密用户的密码(例如,纯文本中的0)以生成密钥,例如,   db90e7eb。
      4.客户端随机生成一个字符串,例如20926330   5.客户端根据每个参数生成要加密的纯文本字符串。以下是一个例子:
      20926330 $ AD75B1697FB5EB6345B2D412124030D2 $ 10086 $ 10086 $ 10.164.111 $ ABCDEFGH $保留$ CTC
      6.客户端使用3DES算法加密字符串以生成验证器。以下是代码示例:
      567A7A72AE33C8867936AB0190EC9F2405B20D4A4808D2A8E8CBC0D7D5482E4F53454EA4F37A29B81A63ECB0BF717E96505EE59476799D932F16AEBFECE097171159095DC57DA84D91930AF92EF96E75486DEA0DEA781D51

    他们也有这个代码(我认为java)的例子,我也需要它在PHP中的等价物:

    public class DESUtil
    {
        private static final String Algorithm = "DESede/ECB/PKCS5Padding";// DESede/ECB/PKCS5Padding;DESede
    
        private static final String DESede = "DESede";
    
        public static byte[] encrypt(byte[] keybyte, byte[] src)
        throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
        {
            SecretKey deskey = new SecretKeySpec(keybyte, DESede);
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.ENCRYPT_MODE, deskey);
            return c1.doFinal(src);
        }
    
        public static byte[] decrypt(byte[] keybyte, byte[] src)
            throws NoSuchAlgorithmException, NoSuchPaddingException, Exception
        {
            SecretKey deskey = new SecretKeySpec(keybyte, DESede);
            Cipher c1 = Cipher.getInstance(Algorithm);
            c1.init(Cipher.DECRYPT_MODE, deskey);
            return c1.doFinal(src);
        }
    
        public static String byte2hex(byte[] b)
        {
            StringBuffer hs = new StringBuffer();
            String stmp = "";
            for (int n = 0; n <b.length; n++)
            {
                stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
                if (stmp.length() == 1)
                    hs.append("0").append(stmp);
                else
                    hs.append(stmp);
            }
            return hs.toString().toUpperCase(Locale.getDefault());
        }
    
        public static byte[] hex2byte(String hexStr)
        {
            if (hexStr.length() % 2 != 0)
            {
                AppLogger.error("hex2bytes's hexStr length is not even.");
                return null;
            }
    
            byte[] toBytes = new byte[hexStr.length() / 2];
            for (int i = 0, j = 0; i <hexStr.length(); j++, i = i + 2)
            {
                int tmpa = Integer.decode(
                    "0X" + hexStr.charAt(i) + hexStr.charAt(i + 1)).intValue();
                toBytes[j] = (byte) (tmpa & 0XFF);
            }
            return toBytes;
        }
    
    
        public static void main(String[] args)
        {
            Security.addProvider(new com.sun.crypto.provider.SunJCE());
            final byte[] rawKey = "db90e7eb".getBytes();
            final byte[] keyBytes = new byte[24];
    
            for (int i = 0; i <rawKey.length; i++)
            {
                keyBytes[i] = rawKey[i];
            }
    
            for (int i = rawKey.length; i <keyBytes.length; i++)
            {
                keyBytes[i] = (byte)0;
            }
    
            String szSrc = "20926330$AD75B1697FB5EB6345B2D412124030D2$10086$10086$10.164.111$ABCDEFGH$Reserved$CTC";
            System.out.println("string before encrypt:" + szSrc);
            byte[] encoded = null;
    
            try
            {
                encoded = encrypt(keyBytes, szSrc.getBytes());
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            System.out.println("string after encrypt::" + byte2hex(encoded));
    
            byte[] srcBytes = null;
    
            try
            {
                srcBytes = decrypt(keyBytes, encoded);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            System.out.println("string before decode: :" + (new String(srcBytes)));
        }
    }
    

    我基于一些在线参考文件做的PHP代码如下,但api似乎不喜欢它,加密代码长度似乎太长,这是我的代码+ api的响应的结果:

      

    加密:   y8V17%2BEImP88UyoQRfGbjldYjfGzsR4r%2B04sE1kPOwPdQNeH1jEhZMYTAgdgeinT6A%2BUfXCFI5KN9QDCTq2oz7AZqTlFEfztQRdgW2ij6YvwQVbRsblJwA%3D%3D

         

    解密   15173232 $ $ BCE723AE4BC97FAD6293D73B2266361D $ 20140409 20140409 $$ ABCDEFGH $保留$ CTC

         

    加密的十六进制:   793856313725324245496D50383855796F51526647626A6C64596A66477A7352347225324230347345316B504F775064514E6548316A45685A4D59544167646765696E543641253242556658434649354B4E395144435471326F7A37415A71546C4645667A74515264675732696A365976775156625273626C4A7741253344253344

         

    3des身份验证员:   y8V17%2BEImP88UyoQRfGbjldYjfGzsR4r%2B04sE1kPOwPdQNeH1jEhZMYTAgdgeinT6A%2BUfXCFI5KN9QDCTq2oz7AZqTlFEfztQRdgW2ij6YvwQVbRsblJwA%3D%3D

         

    SimpleXMLElement对象(

    [retmsg] => 3DES decrypt error second time(0x30), please check epg's encrytMode and acs's encryMode.
    

    要检查我的PHP代码是否有任何错误的细节:

    $userid = '123';
    $terminalip = '';
    $mac = 'ABCDEFGH';
    $terminalid = $userid;
    $pin = '123';
    $encToken = 'testtest';
    
    $encryption_key = $pin;
    $authenticator = rand(0,99999999).'$'.$encToken.'$'.$userid.'$'.$terminalid.'$'.$terminalip.'$'.$mac.'$'.'Reserved'.'$'.'CTC';
    
    $desEncryptedData = encrypt($authenticator, $encryption_key);
    echo "encrypted: <br>".$desEncryptedData;
    echo"<br><br><br><b>Decrypt</b><br>";
    $d = decrypt($desEncryptedData,$encryption_key);
    echo $d;
    
    echo "<BR><BR>encrypted hex: <br>". strToHex($desEncryptedData);
    
    echo "<br><br>3des authenticator: <br>".$desEncryptedData."<br />";
    
    
    $req = "<?xml version='1.0' encoding='UTF-8'?>
    <AuthenticateReq>
    <userid>$userid</userid>
    <authenticator>$desEncryptedData</authenticator>
    </AuthenticateReq>
    ";
    
    // the functions to use to login
    $context = stream_context_create(array('http'=>array(
        'method' => 'POST',
        'header'  => "Content-Type: text/xml\r\n",
        'content' => $req
    )));
    
    
    function encrypt($input,$ky)
    {
        $key = $ky;
        $size = mcrypt_get_block_size(MCRYPT_TRIPLEDES, 'ecb');
        $input = pkcs5_pad($input, $size);
        $td = mcrypt_module_open(MCRYPT_TRIPLEDES, '', 'ecb', '');
        $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $data = mcrypt_generic($td, $input);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);
        $data = base64_encode($data);
        $data = urlencode($data); //push it out so i can check it works
        return $data;
    }
    
    function decrypt($crypt,$ky)
    {
    
        $crypt = urldecode($crypt);
        $crypt = base64_decode($crypt);
        $key = $ky;
        $td = mcrypt_module_open (MCRYPT_TRIPLEDES, '', 'ecb', '');
        $iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
        mcrypt_generic_init($td, $key, $iv);
        $decrypted_data = mdecrypt_generic ($td, $crypt);
        mcrypt_generic_deinit ($td);
        mcrypt_module_close ($td);
        $decrypted_data = pkcs5_unpad($decrypted_data);
        $decrypted_data = rtrim($decrypted_data);
        return $decrypted_data;
    }
    
    function pkcs5_pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen($text) % $blocksize);
        return $text . str_repeat(chr($pad), $pad);
    }
    
    function pkcs5_unpad($text)
    {
        $pad = ord($text{strlen($text)-1});
        if ($pad > strlen($text)) return false;
        return substr($text, 0, -1 * $pad);
    }
    
    function strToHex($string){
        $hex = '';
        for ($i=0; $i<strlen($string); $i++){
            $ord = ord($string[$i]);
            $hexCode = dechex($ord);
            $hex .= substr('0'.$hexCode, -2);
        }
        return strToUpper($hex);
    }
    

    非常感谢您的提前时间

0 个答案:

没有答案