Xiaofeng_Go 2021-09-27 14:22 采纳率: 0%
浏览 1184

做AES加密,解密后出现乱码,偶现,不是中文utf-8原因,求问是什么原因

这个问题已经困扰我1个多星期了,身边的同事问了遍也没搞清楚,第一次来在网上发问题,希望可以得到帮助,谢谢!
就是将post请求参数加密后再传给后台,加密用的AES,key是请求接口从后台获取的,然后就出现偶现的,传给后台的密文解开后是乱码,然后用相同的key和密文用我的加解密工具类解开也是乱码,相当于我自己加密的得到密文,我自己解开是乱码。加密工具类如下

package com.truckerpath.services.backend.security;

import android.util.Base64;
import android.util.Log;

import com.truckerpath.managers.sign.ServerDateManager;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * AES 对称加密算法,加解密工具类
 */
public class SecurityAESUtils {
    /**
     * 加密算法
     */
    private static final String KEY_ALGORITHM = "AES";

    /**
     * AES 的 密钥长度,32 字节,范围:16 - 32 字节
     */
    public static final int SECRET_KEY_LENGTH = 32;

    /**
     * 字符编码
     */
    private static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;

    /**
     * 秘钥长度不足 16 个字节时,默认填充位数
     */
    private static final String DEFAULT_VALUE = "0";
    /**
     * 加解密算法/工作模式/填充方式
     */
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";

    private static String secretKey;
    private static Long securityKeyTime = 0L;
    public static Boolean isEncrypt = true;

    public static boolean isExpireKey(){
        if (securityKeyTime <= ServerDateManager.getInstance().getSynDate()){
            return true;
        }
        return  false;
    }

    public static void setSecretKey(String secretKey, Long time) {
        SecurityAESUtils.secretKey = secretKey;
        securityKeyTime = time;
        Log.i("SecurityInterceptor", "keySecurity = " + secretKey);
    }

    /**
     * AES 加密
     *
     * @param data      待加密内容
     * @return 返回Base64转码后的加密数据
     */
    public static String encrypt(String data) {
        try {
            //创建密码器
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //初始化为加密密码器
            cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
            byte[] encryptByte = cipher.doFinal(data.getBytes(CHARSET_UTF8));
            // 将加密以后的数据进行 Base64 编码
            return base64Encode(encryptByte);
        } catch (Exception e) {
            handleException(e);
        }
        return null;
    }

    /**
     * AES 解密
     *
     * @param base64Data 加密的密文 Base64 字符串
     */
    public static String decrypt(String base64Data) {
        try {
            byte[] data = base64Decode(base64Data);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            //设置为解密模式
            cipher.init(Cipher.DECRYPT_MODE, getSecretKey());
            //执行解密操作
            byte[] result = cipher.doFinal(data);
            return new String(result, CHARSET_UTF8);
        } catch (Exception e) {
            handleException(e);
        }
        return null;

| 表头 | 表头 |
| ------ | ------ |
| 单元格 | 单元格 |
| 单元格 | 单元格 |

    }

    /**
     * 使用密码获取 AES 秘钥
     */
    public static SecretKeySpec getSecretKey() {
        secretKey = toMakeKey(SECRET_KEY_LENGTH, DEFAULT_VALUE);
        return new SecretKeySpec(secretKey.getBytes(CHARSET_UTF8), KEY_ALGORITHM);
    }

    /**
     * 如果 AES 的密钥小于 {@code length} 的长度,就对秘钥进行补位,保证秘钥安全。
     *
     * @param length    密钥应有的长度
     * @param text      默认补的文本
     * @return 密钥
     */
    private static String toMakeKey(int length, String text) {
        // 获取密钥长度
        int strLen = secretKey.length();
        // 判断长度是否小于应有的长度
        if (strLen < length) {
            // 补全位数
            StringBuilder builder = new StringBuilder();
            // 将key添加至builder中
            builder.append(secretKey);
            // 遍历添加默认文本
            for (int i = 0; i < length - strLen; i++) {
                builder.append(text);
            }
            // 赋值
            secretKey = builder.toString();
        }
        return secretKey;
    }

    /**
     * 将 Base64 字符串 解码成 字节数组
     */
    public static byte[] base64Decode(String data) {
        return Base64.decode(data,Base64.NO_WRAP);
    }

    /**
     * 将 字节数组 转换成 Base64 编码
     */
    public static String base64Encode(byte[] data) {
        return Base64.encodeToString(data, Base64.NO_WRAP);
    }

    /**
     * 处理异常
     */
    private static void handleException(Exception e) {
        e.printStackTrace();
        Log.i("SecurityInterceptor","SecurityAESUtils  erro = " + e.getMessage());
    }
}

然后传给后台的方式如下

img

图片中就是我讲参数加密后,放入data中再给后台

然后报错的明文和密文是这样的

img


图中上面的data 是后台接
收到到的我的密文参数,下面的data是后台用这个密文解开得到的乱码,datajson里是我加密前的明文。首先可以排除中文没有用utf-8,没有中文而且用了这个编码。然后我压测了这个加密工具类,相同的key和明文不会加密出不同的密文,压测几十万次都没出现。还有一点就我用相同的明文和key加密得到的密文,比那个解密出乱码的错误密文要长一倍。大家看看是什么原因导致的乱码啊,帮帮忙,谢谢

  • 写回答

4条回答 默认 最新

  • 想想小农 2021-09-27 14:45
    关注

    加密之后得数据是hex码,你需要转成ASC码在上送

    评论

报告相同问题?

问题事件

  • 创建了问题 9月27日

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大