zoukankan      html  css  js  c++  java
  • PHP DES-ECB加密对接Java解密

    最近公司有个业务,需要对接第三方接口,但是参数是需要加密的,对方也只提供了一个java的demo,在网上到处搜索,没有找到直接就能用的方法,后来还是跟公司的Android工程师对接出来的,在这里记录一下大致的流程。
    首先说明一下对方要求的接口请求方式,格式为:http://ip:port/interface/method?data=摘要@@16进制字符串
    说明:

    
    1. 请求参数需要组合成a=1&b=2&c=3格式的参数串;
    2. 摘要的生成方法为md5('a=1&b=2&c=3');
    3. 16进制字符串的生成方法是将参数串进行**对称加密(DES-ECB)**后再转成16进制字符串(bin2hex函数);
    
    

    对方提供的demo(java版本)如下:

    
    public class DesUtils {
    
        /** 默认密钥 */
        private static String strDefaultKey = "seeyonssokey";
    
        /** 加密工具 */
        private Cipher encryptCipher;
    
        /** 解密工具 */
        private Cipher decryptCipher;
    
        /**
         * 加密字符串
         * @param strIn 需加密的字符串
         * @return 加密后的字符串
         * @throws Exception
         */
        public String encrypt(String strIn) throws Exception {
            return byteArr2HexStr(encryptCipher.doFinal(strIn.getBytes()));
        }
    
        /**
         * 解密字符串
         * @param strIn 需解密的字符串
         * @return 解密后的字符串
         * @throws Exception
         */
        public String decrypt(String strIn) throws Exception {
            return new String(decryptCipher.doFinal(hexStr2ByteArr(strIn)));
        }
    
        /**
         * 将 byte 数组转换为表示 16 进制值的字符串, 如: byte[]{8,18} 转换为: 0813 , 和 public static
         * byte[] hexStr2ByteArr(String strIn) 互为可逆的转换过程
         * @param arrB 需要转换的 byte 数组
         * @return 转换后的字符串
         * @throws Exception 本方法不处理任何异常,所有异常全部抛出
         */
        public static String byteArr2HexStr(byte[] arrB) throws Exception {
            int iLen = arrB.length;
            // 每个byte用两个字符才能表示,所以字符串的长度是数组长度的两倍
            StringBuffer sb = new StringBuffer(iLen * 2);
            for(int i = 0; i < iLen; i++) {
                int intTmp = arrB[i];
                // 把负数转换为正数
                while(intTmp < 0) {
                    intTmp = intTmp + 256;
                }
                // 小于0F的数需要在前面补0
                if(intTmp < 16) {
                    sb.append("0");
                }
                sb.append(Integer.toString(intTmp, 16));
            }
            return sb.toString();
        }
    
        /**
         * 将 表 示 16 进 制 值 的 字 符 串 转 换 为 byte 数 组 , 和 public static String
         * byteArr2HexStr(byte[] arrB) 互为可逆的转换过程
         * @param strIn 需要转换的字符串
         * @return 转换后的 byte 数组
         * @throws Exception 本方法不处理任何异常,所有异常全部抛出
         * @author <a href="mailto:leo841001@163.com">LiGuoQing</a>
         */
        public static byte[] hexStr2ByteArr(String strIn) throws Exception {
            byte[] arrB = strIn.getBytes();
            int iLen = arrB.length;
            // 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
            byte[] arrOut = new byte[iLen / 2];
            for(int i = 0; i < iLen; i = i + 2) {
                String strTmp = new String(arrB, i, 2);
                arrOut[i / 2] = (byte)Integer.parseInt(strTmp, 16);
            }
            return arrOut;
        }
    
        /**
         * 从指定字符串生成密钥,密钥所需的字节数组长度为 8 位 不足 8 位时后面补 0 , 超出 8 位只取前 8 位
         * @param arrBTmp 构成该字符串的字节数组
         * @return 生成的密钥
         * @throws java.lang.Exception
         */
        private static Key getKey(byte[] arrBTmp) throws Exception {
            // 创建一个空的8位字节数组(默认值为0)
            byte[] arrB = new byte[8];
            // 将原始字节数组转换为8位
            for(int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
                arrB[i] = arrBTmp[i];
            }
            // 生成密钥
            Key key = new SecretKeySpec(arrB, "DES");
            return key;
        }
    
        public static String encrypt(String strIn, String secretkey) throws Exception {
            Key key = getKey(secretkey.getBytes("utf-8"));
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return byteArr2HexStr(cipher.doFinal(strIn.getBytes("utf-8")));
        }
    
        public static String decrypt(String strIn, String secretkey) throws Exception {
            Key key = getKey(secretkey.getBytes("utf-8"));
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] param = cipher.doFinal(hexStr2ByteArr(strIn));
            return new String(param, "utf-8");
        }
    }
    

    PHP实现加密功能的的方法有两种:

    • mcrypt方式(适用于php7.0以前的版本):
    
    <?php
    
    $text = 'a=1&b=2&c=3';  //参数串
    $key = 'abcd1234';      // 密钥
    echo $ret = self::encryptForDES($text , $key);  //加密
    
    /**
     * 字符串加密(加密方法:DES-ECB)
     * @param string $input 待加密字符串
     * @param string $key 对称加密密钥
     * @return string
     */
    function encryptData($input, $key)
    {
        $size = mcrypt_get_block_size('des','ecb'); // 计算加密算法的分组大小
        $input = self::pkcs5_pad($input, $size);    // 对字符串进行补码
        $td = mcrypt_module_open('des', '', '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 = bin2hex($data); // 将加密后的字符串转化为16进制
        return $data;
    }
    
    /**
     - 对字符串进行补码
     - @param string $text 原字符串
     - @param string $blockSize 加密算法的分组大小
     - @return string
     */
    function pkcs5_pad($text, $blockSize)
    {
        $pad = $blockSize - (strlen($text) % $blockSize);
        return $text . str_repeat(chr($pad), $pad);
    }
    

    输出为:990389f0aad8d12014ca6a45cd72cdf7

    • openssl方式(适用于php7.0以后的版本):
    
    <?php
    
    $text = 'a=1&b=2&c=3';            // 参数串
    $key = 'abcd1234';                // 密钥
    echo encryptData($text, $key);    // 加密
    
    /**
     * 字符串加密(加密方法:DES-ECB)
     * @param string $input 待加密字符串
     * @param string $key 对称加密密钥
     * @return string
     */
    function encryptData($input, $key)
    {
        $ivlen = openssl_cipher_iv_length('DES-ECB');    // 获取密码iv长度
        $iv = openssl_random_pseudo_bytes($ivlen);        // 生成一个伪随机字节串
        $data = openssl_encrypt($input, 'DES-ECB', $key, $options=OPENSSL_RAW_DATA, $iv);    // 加密
        return bin2hex($data);
    }
    
    

    输出为:990389f0aad8d12014ca6a45cd72cdf7

    原文地址:https://segmentfault.com/a/1190000016888916

  • 相关阅读:
    uNFS搭建
    nodejs+koa 后台框架结构、demo学习地址
    Apache 基本配置 代理 重定向 跨域 https ssl证书 在windows下常用命令
    新版 Mediasoup Windows 安装 编译
    腾讯云服务器,在本地域名不能访问,IP可以访问;端口访问差异:有的地方能访问有的不能
    nodejs 程序打包 打包 koa express 项目 源代码保护加密
    windows 设置修改本地 hosts 访问 github 快速访问 提高访问 github 速度
    Flutter开发 备用网站地址
    redis in windows
    CRLF和LF的差异
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9964006.html
Copyright © 2011-2022 走看看