携程供应商接口数据解密AES/CBC/PKCS5Padding

原创
2018/02/08 16:44
阅读数 813

    function aes128_cbc_encrypt($key, $data, $iv) {
        if(16 !== strlen($key)) $key = hash('MD5', $key, true);
        if(16 !== strlen($iv)) $iv = hash('MD5', $iv, true);
        $padding = 16 - (strlen($data) % 16);
        $data .= str_repeat(chr($padding), $padding);
        return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
    }

    function aes128_cbc_decrypt($key, $data, $iv) {
        if(16 !== strlen($key)) $key = hash('MD5', $key, true);
        if(16 !== strlen($iv)) $iv = hash('MD5', $iv, true);
        $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, $iv);
        $padding = ord($data[strlen($data) - 1]);
        return substr($data, 0, -$padding);
    }

    function decode_bytes($text){
        $bytes=array();
        for($i=0;$i<strlen($text);$i+=2){
            $char=$text[$i];
            $bytes[$i/2]=chr((ord($char)-ord('a'))<<4);
            $char=$text[$i+1];
            $bytes[$i/2]=chr(ord($bytes[$i/2])+(ord($char)-ord('a')));
        }

        return join('',$bytes);
    }

    function encode_bytes($text){
        $bytes=array();
        for($i=0;$i<strlen($text);$i++){
            $bytes[]=chr(((ord($text[$i])>>4)&15)+ord('a'));
            $bytes[]=chr((ord($text[$i]) & 15)+ord('a'));
        }

        return join('',$bytes);
    }

    function test(){
        $key='';
        $vt='';
               //$encrypted='jojihabbaogpamnnggmlkpflpmogmlclkeoglcikapgpbconldjjmlfjapfblhnobglgakiehkcgfnnmbojfpgmbcnfbjlcfjpjgcgjoanihcaiiafggfgnnjflfccgj';
        $encrypted=$this->encode_bytes($this->aes128_cbc_encrypt($key,'123',$vt));
        $foo = $this->aes128_cbc_decrypt($key,$this->decode_bytes($encrypted),$vt);
        pr($foo);
        
    }

PKCS5Padding与PKCS7Padding当数据块大小是8时是一样的效果,事实上PKCS5Padding不能直接用户在AES上,因为AES要求的数据块至少是16字节以上。所以PKCS5Padding实际上是PKCS7Padding的别名来用。

Credit https://gist.github.com/RiANOl/1077723

JAVA AES

/**
     * 加密方法
     *
     * @param encData   要加密的数据
     * @param secretKey  密钥,16位的数字和字母
     * @param vector     初始化向量,16位的数字和字母
     * @return
     * @throws Exception
     */
    public static String encrypt(String encData, String secretKey, String vector) {
        try {
            byte[] raw = secretKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
            IvParameterSpec iv = new IvParameterSpec(vector.getBytes("utf-8"));// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8"));
            return encodeBytes(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密方法
     *
     * @param decData   要解密的数据
     * @param secretKey  密钥 ,16位的数字和字母
     * @param vector     初始化向量,16位的数字和字母
     * @return
     * @throws Exception
     */
    public static String decrypt(String decData, String secretKey, String vector) {
        try {
            byte[] raw = secretKey.getBytes("utf-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(vector.getBytes("utf-8"));
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = decodeBytes(decData);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original, "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 转16进制
     *
     * @param bytes
     * @return
     */
    public static String encodeBytes(byte[] bytes) {
        StringBuffer strBuf = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
            strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
        }
        return strBuf.toString();
    }

    /**
     * 转字节数组
     *
     * @param str
     * @return
     */
    public static byte[] decodeBytes(String str) {
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length(); i += 2) {
            char c = str.charAt(i);
            bytes[i / 2] = (byte) ((c - 'a') << 4);
            c = str.charAt(i + 1);
            bytes[i / 2] += (c - 'a');
        }
        return bytes;
    }

 

展开阅读全文
加载中
点击加入讨论🔥(2) 发布并加入讨论🔥
打赏
2 评论
1 收藏
1
分享
返回顶部
顶部