不同语言AES加密结果不同

薄洪涛6年前PHP1336

最近一直在和某保险公司的联调接口,他们的接口是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加密

相关文章

Yii2.0框架ActiveForm总结

首先引入ActiveForm和Html这里两个是很重要的<?php     use yii\bootstrap\ActiveForm; &nbs...

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

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

Yii2.0行为Behavior的理解

Yii2.0行为Behavior的理解

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

Elasticsearch第三篇之全文搜索及在Yii2.0中的使用

Elasticsearch第三篇之全文搜索及在Yii2.0中的使用

前几天做了一个模块,大数据的搜索,其实也不是特别大,组合起来差不多800万左右,用的是mysql数据库,需求有这么变态的两点;需要按照地址去搜索按照起止时间去搜索别的不说,就这两条,mysql也就只能...

Elasticsearch为什么搜索那么快?

Elasticsearch为什么搜索那么快?

介绍Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lu...

YII2场景值的使用

开发的时候添加和编辑写在了一个方法里面,上传图片添加的时候需要验证为空,编辑的时候不需要,这时候yii的场景值能够解决这个问题:控制器中$model = new News...

发表评论    

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