你知道的越多,你不知道的越多
点赞再看,养成习惯
如果您有疑问或者见解,欢迎指教:
企鹅:869192208
前言
在系统实际开发过程中,我们与外部接口的数据对接的时候,基于数据传输安全等因素的考量,经常需要对接口传输的参数进行AES加密方案,以下是模拟对接的数据加密要求:
加密说明:
数据传输和返回的结果都用AES加密处理
AESKey:125858a550c605c199c19d778b81327b
AESIV:0392039203920300
原文示例:{“typeAction”:0}
加密后的字符串为:9KdUttr+dfXTvUTSPAmxVA3l+5kR2+zPkc2N2PJiic8=
在线AES加解密测试地址:http://tool.chacuo.net/cryptaes
以上所有入参都进过加密处理 示例:
{“jsonParam”:“Mxqe9kbyWyvR64n/kiEQK7M1kGMqCZ3KgFg8Z5EVI/XajilAz16Ed7sK156EShTqwOrmZb7QdOWF/kbj2KJa/jmO+ylIe+9vdrqRRFxddY4=”}
返回参数示例:
{“errcode”:0,“data”:“lKGC/SI9dsTWZ6vc8Wtvvm0w9NZxR3XyhnlVeWq+cQkK+yce7uWr61KvZ5Eomgue44omSx2fhHef\r\nqFwWrpnM9+YLLPn5z/ODbDkshZg6/yMlTtC1PnvfNPfqN/tDscBE\r\n”,“errmsg”:“”}
因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。
替换的文件:%JDK_HOME%\jre\lib\security\local_policy.jar
官方网站提供了JCE无限制权限策略文件的下载:
- JDK6的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
- JDK7的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
- JDK8的下载地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security下覆盖原来文件,记得先备份。
如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security下。
jce_policy资源合辑地址:https://download.csdn.net/download/CDWLX/12231194
下面是经过测试的完整代码:
- 方案一
package xymy;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
* AES工具类
*
* <pre>
* 因为某些国家的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。比如默认不允许256位密钥的AES加解密,解决方法就是修改策略文件。
* 替换的文件:%JDK_HOME%\jre\lib\security\local_policy.jar
* 参考: http://czj4451.iteye.com/blog/1986483
*/
public class AESTest {
// 密钥
public static String AESKey = "125858a550c605c199c19d778b81327b";
public static String AESIV = "0392039203920300";
private static String charset = "utf-8";
// 偏移量
private static int offset = 16;
private static String transformation = "AES/CBC/PKCS5Padding";
private static String algorithm = "AES";
/**
* 加密
*
* @param content
* @return
*/
public static String encrypt(String content) {
return encrypt(content, AESKey);
}
/**
* 解密
*
* @param content
* @return
*/
public static String decrypt(String content) {
return decrypt(content, AESKey);
}
/**
* 加密
*
* @param content
* 需要加密的内容
* @param AESKey
* 加密密码
* @return
*/
public static String encrypt(String content, String AESKey) {
try {
SecretKeySpec skey = new SecretKeySpec(AESKey.getBytes(), algorithm);
IvParameterSpec iv = new IvParameterSpec(AESIV.getBytes(), 0, offset);
Cipher cipher = Cipher.getInstance(transformation);
byte[] byteContent = content.getBytes(charset);
cipher.init(Cipher.ENCRYPT_MODE, skey, iv);// 初始化
byte[] result = cipher.doFinal(byteContent);
return new Base64().encodeToString(result); // 加密
} catch (Exception e) {
System.out.println(e);
}
return null;
}
/**
* AES(256)解密
*
* @param content
* 待解密内容
* @param AESKey
* 解密密钥
* @return 解密之后
* @throws Exception
*/
public static String decrypt(String content, String AESKey) {
try {
SecretKeySpec skey = new SecretKeySpec(AESKey.getBytes(), algorithm);
IvParameterSpec iv = new IvParameterSpec(AESIV.getBytes(), 0, offset);
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, skey, iv);// 初始化
byte[] result = cipher.doFinal(new Base64().decode(content));
return new String(result); // 解密
} catch (Exception e) {
System.out.println(e);
}
return null;
}
public static void main(String[] args) throws Exception {
String s = "{\"code\":\"YWBD_GLLR\",\"params\":[{\"name\":\"ID\",\"value\":\"01265a3dc493462e9cdd4a26c41f19de\"}]}";
// 加密
System.out.println("加密前:" + s);
String encryptResultStr = encrypt(s);
System.out.println("加密后:" + encryptResultStr);
// 解密
System.out.println("解密后:" + decrypt(encryptResultStr));
}
}
运行结果:
- 方案二
Encodes.java
/**
* Copyright (c) 2005-2012 springside.org.cn
*/
package com.xymy.common.utils;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;
/**
* 封装各种格式的编码解码工具类. 1.Commons-Codec的 hex/base64 编码 2.自制的base62 编码
* 3.Commons-Lang的xml/html escape 4.JDK提供的URLEncoder
*
* @author calvin
* @version 2013-01-15
*/
public class Encodes {
private static final String DEFAULT_URL_ENCODING = "UTF-8";
private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
.toCharArray();
/**
* Hex编码.
*/
public static String encodeHex(byte[] input) {
return new String(Hex.encodeHex(input));
}
/**
* Hex解码.
*/
public static byte[] decodeHex(String input) {
try {
return Hex.decodeHex(input.toCharArray());
} catch (DecoderException e) {
throw Exceptions.unchecked(e);
}
}
public static byte[] stringToByte(String input) {
return input.getBytes();
}
/**
* Base64编码.
*/
public static String encodeBase64(byte[] input) {
return new String(Base64.encodeBase64(input));
}
/**
* Base64编码.
*/
public static String encodeBase64(String input) {
try {
return new String(Base64.encodeBase64(input
.getBytes(DEFAULT_URL_ENCODING)));
} catch (UnsupportedEncodingException e) {
return "";
}
}
// /**
// * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
// */
// public static String encodeUrlSafeBase64(byte[] input) {
// return Base64.encodeBase64URLSafe(input);
// }
/**
* Base64解码.
*/
public static byte[] decodeBase64(String input) {
return Base64.decodeBase64(input.getBytes());
}
/**
* Base64解码.
*/
public static String decodeBase64String(String input) {
try {
return new String(Base64.decodeBase64(input.getBytes()),
DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* Base62编码。
*/
public static String encodeBase62(byte[] input) {
char[] chars = new char[input.length];
for (int i = 0; i < input.length; i++) {
chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
}
return new String(chars);
}
/**
* Html 转码.
*/
public static String escapeHtml(String html) {
return StringEscapeUtils.escapeHtml4(html);
}
/**
* Html 解码.
*/
public static String unescapeHtml(String htmlEscaped) {
return StringEscapeUtils.unescapeHtml4(htmlEscaped);
}
/**
* Xml 转码.
*/
public static String escapeXml(String xml) {
return StringEscapeUtils.escapeXml(xml);
}
/**
* Xml 解码.
*/
public static String unescapeXml(String xmlEscaped) {
return StringEscapeUtils.unescapeXml(xmlEscaped);
}
/**
* URL 编码, Encode默认为UTF-8.
*/
public static String urlEncode(String part) {
try {
return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
/**
* URL 解码, Encode默认为UTF-8.
*/
public static String urlDecode(String part) {
try {
return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
throw Exceptions.unchecked(e);
}
}
}
Exceptions.java
/**
* Copyright (c) 2005-2012 springside.org.cn
*/
package com.xymy.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
/**
* 关于异常的工具类.
* @author calvin
* @version 2013-01-15
*/
public class Exceptions {
/**
* 将CheckedException转换为UncheckedException.
*/
public static RuntimeException unchecked(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new RuntimeException(e);
}
}
/**
* 将ErrorStack转化为String.
*/
public static String getStackTraceAsString(Throwable e) {
if (e == null){
return "";
}
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* 判断异常是否由某些底层的异常引起.
*/
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
Throwable cause = ex.getCause();
while (cause != null) {
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
if (causeClass.isInstance(cause)) {
return true;
}
}
cause = cause.getCause();
}
return false;
}
/**
* 在request中获取异常类
* @param request
* @return
*/
public static Throwable getThrowable(HttpServletRequest request){
Throwable ex = null;
if (request.getAttribute("exception") != null) {
ex = (Throwable) request.getAttribute("exception");
} else if (request.getAttribute("javax.servlet.error.exception") != null) {
ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
}
return ex;
}
}
Cryptos.java
package com.xymy.common.security;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.xymy.common.utils.Encodes;
import com.xymy.common.utils.Exceptions;
/**
* 支持HMAC-SHA1消息签名 及 DES/AES对称加密的工具类.
*
* 支持Hex与Base64两种编码方式.
*
* @author calvin
*/
public class Cryptos {
private static final String AES = "AES";
private static final String AES_CBC = "AES/CBC/PKCS5Padding";
private static final String HMACSHA1 = "HmacSHA1";
private static final String DEFAULT_URL_ENCODING = "UTF-8";
private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
private static final int DEFAULT_AES_KEYSIZE = 128;
private static final int DEFAULT_IVSIZE = 16;
private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125};
private static SecureRandom random = new SecureRandom();
//-- HMAC-SHA1 funciton --//
/**
* 使用HMAC-SHA1进行消息签名, 返回字节数组,长度为20字节.
*
* @param input 原始输入字符数组
* @param key HMAC-SHA1密钥
*/
public static byte[] hmacSha1(byte[] input, byte[] key) {
try {
SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
Mac mac = Mac.getInstance(HMACSHA1);
mac.init(secretKey);
return mac.doFinal(input);
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 校验HMAC-SHA1签名是否正确.
*
* @param expected 已存在的签名
* @param input 原始输入字符串
* @param key 密钥
*/
public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
byte[] actual = hmacSha1(input, key);
return Arrays.equals(expected, actual);
}
/**
* 生成HMAC-SHA1密钥,返回字节数组,长度为160位(20字节).
* HMAC-SHA1算法对密钥无特殊要求, RFC2401建议最少长度为160位(20字节).
*/
public static byte[] generateHmacSha1Key() {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1);
keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
//-- AES funciton --//
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
*/
public static String aesEncrypt(String input) {
try {
return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
*/
public static String aesEncrypt(String input, String key) {
try {
return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
*/
public static byte[] aesEncrypt(byte[] input, byte[] key) {
return aes(input, key, Cipher.ENCRYPT_MODE);
}
/**
* 使用AES加密原始字符串.
*
* @param input 原始输入字符数组
* @param key 符合AES要求的密钥
* @param iv 初始向量
*/
public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.ENCRYPT_MODE);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
*/
public static String aesDecrypt(String input) {
try {
return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
*/
public static String aesDecrypt(String input, String key) {
try {
return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
} catch (UnsupportedEncodingException e) {
return "";
}
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
*/
public static byte[] aesDecrypt(byte[] input, byte[] key) {
return aes(input, key, Cipher.DECRYPT_MODE);
}
/**
* 使用AES解密字符串, 返回原始字符串.
*
* @param input Hex编码的加密字符串
* @param key 符合AES要求的密钥
* @param iv 初始向量
*/
public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
return aes(input, key, iv, Cipher.DECRYPT_MODE);
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
*/
private static byte[] aes(byte[] input, byte[] key, int mode) {
try {
SecretKey secretKey = new SecretKeySpec(key, AES);
Cipher cipher = Cipher.getInstance(AES);
cipher.init(mode, secretKey);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
*
* @param input 原始字节数组
* @param key 符合AES要求的密钥
* @param iv 初始向量
* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
*/
private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
try {
SecretKey secretKey = new SecretKeySpec(key, AES);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(AES_CBC);
cipher.init(mode, secretKey, ivSpec);
return cipher.doFinal(input);
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
*/
public static String generateAesKeyString() {
return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
}
/**
* 生成AES密钥,返回字节数组, 默认长度为128位(16字节).
*/
public static byte[] generateAesKey() {
return generateAesKey(DEFAULT_AES_KEYSIZE);
}
/**
* 生成AES密钥,可选长度为128,192,256位.
*/
public static byte[] generateAesKey(int keysize) {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
keyGenerator.init(keysize);
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
} catch (GeneralSecurityException e) {
throw Exceptions.unchecked(e);
}
}
/**
* 生成随机向量,默认大小为cipher.getBlockSize(), 16字节.
*/
public static byte[] generateIV() {
byte[] bytes = new byte[DEFAULT_IVSIZE];
random.nextBytes(bytes);
return bytes;
}
}
CryptosTest.java
package xymy;
import org.apache.commons.codec.binary.Base64;
import com.xymy.common.security.Cryptos;
public class CryptosTest {
public static String AESKey = "125858a550c605c199c19d778b81327b";
public static String AESIV = "0392039203920300";
public static String param = "<?xml version=\"1.0\" encoding=\"GBK\"?>\n<SPItemListDef>\n\t<TableCols name=\"YWBD_WHT_HLWWHJYDWBG\" id = \"0\">\n\t\t<List name=\"YWBD_WHT_HLWWHJYGDXX\">\n\t\t\t<TableCols id = \"0\">\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>GDQY</ColName>\n\t\t\t\t\t<ColValue><![CDATA[测试]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>HLWWHJYDWBG_SEQ</ColName>\n\t\t\t\t\t<ColValue><![CDATA[72ed76449b374b3bba77347561dfcc70]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>GDFRXM</ColName>\n\t\t\t\t\t<ColValue><![CDATA[测试]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>SEQ</ColName>\n\t\t\t\t\t<ColValue><![CDATA[2ec5c892b0934f6381b8d2e20dd388c7]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t</TableCols>\n\t\t</List>\n\t\t<Column>\n\t\t\t<ColName>YZSDZ</ColName>\n\t\t\t<ColValue><![CDATA[广州市]]></ColValue>\n\t\t</Column>\n\t\t<Column>\n\t\t\t<ColName>BGSQR</ColName>\n\t\t\t<ColValue><![CDATA[心猿码意]]></ColValue>\n\t\t</Column>\n\t\t<Column>\n\t\t\t<ColName>SEQ</ColName>\n\t\t\t<ColValue><![CDATA[72ed76449b374b3bba77347561dfcc70]]></ColValue>\n\t\t</Column>\n\t</TableCols>\n</SPItemListDef>";
public static void main(String[] args) {
String enCode = enCode(param);
enCode = "sU8EtK9gy/B7sOfrNrtaPf5+b6gcBA2u1i7VYVoIWd0z0S/GJBwR4NQQAaWBjqimZKysWZ3aefH3YN3xqBrG0I1O1q1zlGuDM6+P0JuZFXWOJB90wOvAFywoDBiFb6j3u4s73++BcZpTKV5HpQoWZjIA7eaVjVZX1ML5Z04xNuAnQH2ZM104v/S+5toxt8BbQgI8x1fYfU8vXiHmZkvzc/jGsg8ZDrXKa0utVMdak+EqzGFMAsj7YMclL3YFVQjW1ax0f81CU2oNWD6JMKalLmqFud1QAADhUtRkfsfsMldxLDykFV+Pzpd6OlAX34uPbWOBYdTS/unt0ExZklHE7bU/VYSAhZdZPsfxyO5usUEYMHJtv15Xqk3t8Dq9QZ28NZ1xcRK5nHoEckchLZpQyD5uXWbLdhy2GO4MS+7qSCBgV5QgUgOWN86LZgCPxmkOV5mYBxXtWI2mByOIm4d3ul8D4VBb2I04QDw/iVwOOKXuFzKL1lwuf3p9Z/ZvhTuPkLqVUQoa9f63G2flGSUIZ5oOVzQkBiJ/H/ybpRl19NTAhwZJK5QiD7OgK4DEd0WmrW64pj9Bun1yEQnSknc/zHvQw1WXQiecQ0CKF3uvUG0aOskwdZwDXvcvdXyt8+hEjGZf2CRxVjxgNRcpHl0M/S6kDhk0Yv3NXYTOspmG2SyR2Eofw8YGZxO3yWxqKzIZQOgFdFhygq/Zrtt7CUiw0+0fSRMM8wCzDKeIZr5yUdUiNUQzOdrygC2lGSPrP3GP+RcKGuHBe4N62uBrGj14IDj/74ZPjSiLm3NuOZ7pBGHVqr7RH9Uz9Sjv9coRs3At/ypVSXWpigy6Mi/ZuctnvcgK1tgAXs9QMvxVkJCzuKx0qQL7MArdFMngLySxP+1Z81It9PKXU7olc+koits5BIHWibXMF7TBBX1VDv/af+Kugjs6L+6uKBrU10XmKRrYORSaT81Ws5R5pwb9DK6psL+zjToeKH8mpTrPzPqMxV+qwYK4Yxr91xWblBxMCEdab/BljhtdOB37QrikB3ECXTSg8qWSsp1ciMnVuidP5Dmo0UUxDoKATeYhcM6r20s4v3+6TjoPTDu27lsEAUiKdS2iYCq0QUN4nZ+qehhje8uHU5KFaV9kgdAKN8MECM+GnhK+Uc1Pf02zNnetLYKu7u5bdW57JOE6ldbpu1YbUERNxX609ybDpsm9ixBreRPGy3oaWJ3Tbvtu6wVzK5ATRhfN04WnaI6Z/3H2y8OoC8tbnFdXFFbAeMPMRQIZUy/WG9dzOZ3cuCaak2OKmBWnTqABpd3yNR6ZUZOEiwd36EkGP6zWNrE0J0GlBdugU2b7";
decode(enCode);
}
private static String enCode(String param) {
byte[] aesEncrypt = Cryptos.aesEncrypt(param.getBytes(), AESKey.getBytes(), AESIV.getBytes());
System.out.println("param:" + param);
System.out.println(new Base64().encodeToString(aesEncrypt));
return Base64.encodeBase64String(aesEncrypt);
}
private static void decode(String param) {
System.out.println("param:" + param);
//System.out.println(new String(new Base64().decode(param)) );
byte[] aesDecrypt = Cryptos.aesDecrypt( new Base64().decode(param), AESKey.getBytes(), AESIV.getBytes());
System.out.println(new String(aesDecrypt));
}
}
- 运行结果
注意:在这过程中,遇到了一个坑,那就是解密的时候,最好将传入的解密参数的 " " 替换为 “+” ,否则报错。
以下是实际应用的时候的部分代码:
/**
* 描述:获取表单业务数据xml(参数及返回值均进行AES加密)
* @author xymy
* @date 2020年2月18日 下午4:15:55
* @param request
* @param response
* @param info
* @param params
* @param token
*/
@RequestMapping(value = "getFormDataXMLAES", produces = "text/html;charset=UTF-8")
public void getFormDataXMLAES(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "jsonParam", required = false) String jsonParam,
@RequestParam(value = "token", required = false) String token) {
Map<String, Object> xml;
try {
//properties 文件配置了AESKey和AESIV
String AESKey = Global.getConfig("AESKey");
String AESIV = Global.getConfig("AESIV");
//对入参进行AES解密
byte[] aesDecrypt = Cryptos.aesDecrypt(new Base64().decode(jsonParam.replace(" ", "+")), AESKey.getBytes(), AESIV.getBytes());
jsonParam = new String(aesDecrypt);
//将解密后的json解析为Map,再获取到实际参数
Map<String, Object> maps = JSON.parseObject(jsonParam);
FormInfo info = new FormInfo();
info.setCode(maps.get("code").toString());
String params = maps.get("params").toString();
String returnDataType = maps.get("returnDataType").toString();
logger.info("code:" + maps.get("code").toString() + ",params:" + maps.get("params").toString() + ",returnDataType:" + returnDataType);
if (StringUtils.isNotBlank(token))
token = URLDecoder.decode(token, "utf-8");
boolean isGetXml = true;
if ("json".equals(returnDataType)) {
isGetXml = false;
}
xml = formInfoService.getFromDataXML(info, params, isGetXml, token, request);
...
xml.put("data", Base64.encodeBase64String(Cryptos.aesEncrypt(xml.get("rtnData").toString().getBytes("UTF-8"), AESKey.getBytes(), AESIV.getBytes())));
...
xml.put("errcode", 0);
xml.put("errmsg", null);
} catch (Exception e) {
logger.error(e.getMessage(), e);
...
}
renderString(response, xml);
}