不同语言AES加密结果不同

薄洪涛6年前PHP1153

最近一直在和某保险公司的联调接口,他们的接口是AES加密过的,就是请求的报文体需要加密,返回的报文体需要解密;java实现的,然后我这边用php去调用,发现先了一件诡异的事情,两种语言的加密结果不一致!!!

以下是java代码

package com.aibaoxian.util;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
 
 
public class AESUtil {
    private static final String defaultCharset = "UTF-8";
    private static final String KEY_AES = "AES";
    private static final String KEY_MD5 = "MD5";
    private static MessageDigest md5Digest;
    static {
        try {
            md5Digest = MessageDigest.getInstance(KEY_MD5);
        } catch (NoSuchAlgorithmException e) {
 
        }
    }
 
 
    //加密方法使用示例:
    public static void main(String[] args) throws Exception {
        //这个是aes加密的key,当然我这里是胡乱写的
        String key = "WVBJFZTESTERSS";
        String data = "{\"head\":{\"platform\":\"RBJF\",\"requestType\":10,\"timeStamp\":\"\",\"extTransactionNo\":\"\",\"localTransactionNo\":\"\",\"systemId\":\"\",\"MD5\":\"\",\"errorCode\":\"\",\"errorMessage\":\"\"},\"body\":{\"mainInfo\":{\"channelId\":\"CH10000020\",\"agentCode\":\"\",\"userId\":\"ABX999999\"}}}";
        String encrypted = AESUtil.encrypt(data, key);
        String decrypted = AESUtil.decrypt(encrypted, key);
        System.out.println("加密后的密文\n" + encrypted);
        System.out.println("解密后的报文:\n" + decrypted);
    }
    /**
     * 加密
     *
     * @param data 需要加密的内容
     * @param key 加密密码
     * @return
     */
    public static String encrypt(String data, String key) {
        return doAES(data, key, Cipher.ENCRYPT_MODE);
    }
    /**
     * 解密
     *
     * @param data 待解密内容
     * @param key 解密密钥
     * @return
     */
    public static String decrypt(String data, String key) {
        return doAES(data, key, Cipher.DECRYPT_MODE);
    }
 
 
    /**
     * 加解密
     *
     * @param data
     * @param key
     * @param mode
     * @return
     */
    private static String doAES(String data, String key, int mode) {
        try {
            boolean encrypt = mode == Cipher.ENCRYPT_MODE;
            byte[] content;
            if (encrypt) {
                content = data.getBytes(defaultCharset);
            } else {
                content = Base64.decodeBase64(data.getBytes());
            }
            SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset))
                    , KEY_AES);
            Cipher cipher = Cipher.getInstance(KEY_AES);// 创建密码器
            cipher.init(mode, keySpec);// 初始化
            byte[] result = cipher.doFinal(content);
            if (encrypt) {
                return new String(Base64.encodeBase64(result));
            } else {
                return new String(result, defaultCharset);
            }
        } catch (Exception e) {
        }
        return null;
    }
}

可以看到,调用接口发送数据他是把key用md5加密后,再把报文体用aes加密,最后的结果用base64编码;接口返回的数据,要先进行base64解码,然后aes解码就是报文体;

class AESUtil{
    /**
     *
     * @param string $string 需要加密的字符串
     * @param string $key 密钥
     * @return string
     */
    public static function encrypt($string, $key){
        $key = substr(openssl_digest($key, 'md5', true), 0, 16);
        $data = openssl_encrypt($string, "AES-128-ECB", $key, OPENSSL_RAW_DATA);
        $data = base64_encode($data);
        return $data;
    }
    /**
     * @param string $string 需要解密的字符串
     * @param string $key 密钥
     * @return string
     */
    public static function decrypt($string, $key){
        $key = substr(openssl_digest($key, 'md5', true), 0, 16);
        @$decrypted = openssl_decrypt(base64_decode($string), 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
        return $decrypted;
    }
}

这是我最终调整后的php加密算法,和java的加解密是一致的;

之前的加密算法用的AES-128-CBC,开始解密结果是一致的,但是报文长度超过16位后,加密结果就不一样了

微信图片_20190615103540.png


后来改成了AES-128-ECB就可以了,原因是因为分块加密填充方式不同造成的;

标签: AES加密

相关文章

五十个小技巧提高PHP执行效率

    在项目开发过程中,经常遇到了一些PHP处理程序性能底下的情况,程序运行在centos+nginx环境,虽然这个有很多的原因如:服务器本身配置,运行环境n...

Yii2.0行为Behavior的理解

Yii2.0行为Behavior的理解

在说什么叫行为之前,觉得说下行为的作用比较好;使用行为(behavior)可以在不修改现有类的情况下,对类的功能进行扩充。通过将行为绑定到一个类,可以使得类具有行为本身所具有的属性和方法;在设计原则中...

php高级特性之反射

何为反射?字面理解,就是根据到达找到源;在面向对象编程中的反射就是根据对象去找出它所属的类,及类的方法,详情;首先声明一点,反射在实际开发中用的很少(至少我没用过),但是在编写文档的时候,可以用于文档...

YII2独立开发遇到的坑

    之前开发的时候,遇到图片上传什么的都是直接用前辈们配好的插件等等,换了家公司以后,要自己独立开发项目,顿时遇到了问题,开始是项目的配置,然后在添加的时候遇到了图片上传的问题...

phpstorm配置xdebug

phpstorm配置xdebug

1、首先写个phpinfo文件,然后访问,查看是否有xdebug扩展,如果没有请查看第二步,有的话直接第三步2,安装xdebug扩展,首先复制phpinfo页面所有(phpinfo页面直接ctrl+a...

Elasticsearch第二篇之数据操作

    上一篇向大家讲解了Elasticsearch的部署安装和基本设置,这篇文章就和大家一起熟悉下Elastic的数据库操作,和普通数据库不同,es库需要公告...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。