这个问题已经困扰我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());
}
}
然后传给后台的方式如下
图片中就是我讲参数加密后,放入data中再给后台
然后报错的明文和密文是这样的
图中上面的data 是后台接
收到到的我的密文参数,下面的data是后台用这个密文解开得到的乱码,datajson里是我加密前的明文。首先可以排除中文没有用utf-8,没有中文而且用了这个编码。然后我压测了这个加密工具类,相同的key和明文不会加密出不同的密文,压测几十万次都没出现。还有一点就我用相同的明文和key加密得到的密文,比那个解密出乱码的错误密文要长一倍。大家看看是什么原因导致的乱码啊,帮帮忙,谢谢