公司需求:开发app后台,接口需要采用密文传入传出。
开发思路:
采用RAS非对称公私密钥的方式,app与后台分别有一对公私秘钥,在调用接口和返回接口的时候分别采用对方公钥加密,接到密文后用自己的私钥解密。
由于调用的接口有部分是复用以前开发完成的接口,为避免对每个接口进行修改,因此采用拦截器处理加密与解密的过程。
在开发过程中开始采用RAS非对称秘钥方式处理,但是遇到大量数据时、加密解密效率比较低,因此采用RAS与AES混合秘钥方式,当加密报文长度超过某一值(如:10000),采用AES加密处理。
完整代码:https://download.csdn.net/download/yixin605691235/10620692
核心代码如下:
拦截器代码:
web.xml
<!--配置过滤器-->
<filter>
<filter-name>AuthUserFilter</filter-name>
<filter-class>cn.trawe.aliopen.filter.AuthUserFilter</filter-class>
</filter>
<!--映射过滤器-->
<filter-mapping>
<filter-name>AuthUserFilter</filter-name>
<!--“/*”表示拦截所有的请求 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
package cn.trawe.aliopen.filter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.alibaba.fastjson.JSONObject;
import com.example.util.AES;
import com.example.util.Constant;
import com.example.util.RSAUtils;
public class AuthUserFilter implements Filter {
private static Logger logger = LogManager.getLogger(AuthUserFilter.class);
private FilterConfig config;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
config = filterConfig;
ServletContext sc = filterConfig.getServletContext();
WebApplicationContext cxt = WebApplicationContextUtils.getWebApplicationContext(sc);
//初始化server
logger.info("---【AuthUserFilter】-过滤器初始化----");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ParameterRequestWrapper requestWrapper = new ParameterRequestWrapper((HttpServletRequest) request);
WrapperedResponse wrapResponse = new WrapperedResponse((HttpServletResponse) response);
String type = requestWrapper.getMethod();
String parameter="";
String errResult = "";
// 对request和response进行一些预处理
requestWrapper.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
wrapResponse.setContentType("text/html;charset=UTF-8");
if("POST".equalsIgnoreCase(type) && requestWrapper.getParameter("app_params") == null){
parameter = getBodyString(requestWrapper.getReader());
}else {
parameter = requestWrapper.getParameter("app_params");
}
// 获取访问路径
//没有参数则不去拦截直接放行
if (StringUtils.isEmpty(parameter)) {
chain.doFilter(request, response); // 让目标资源执行,放行
return;
}
//对参数进行解密,转为map
Map<String, Object> paramToMap = getDecryptMap(parameter,type);
JSONObject errorMap = new JSONObject();
errorMap.put("status", "0");
if(paramToMap == null) {
errResult = "app访问类型验证失败";
//返回加密报文
logger.info("【AuthUserFilter】原始返回数据:"+errResult );
errorMap.put("message", errResult);
String encryptStr = getEncryptString(errorMap.toJSONString());
logger.info("【AuthUserFilter】加密后返回数据: " + encryptStr);
writeResponse(response, encryptStr);
return;
}
// 此处还可以进行其他的相关验证,比如token等------
// 此处还可以进行其他的相关验证,比如token等------
//赋值参数调用原请求
setRequestParams(requestWrapper, paramToMap);
chain.doFilter(requestWrapper, wrapResponse); // 让目标资源执行,放行
String result = new String(wrapResponse.getResponseData(), "utf-8");
//返回加密报文
String encryptStr = getEncryptString(result);
writeResponse(response, encryptStr);
}
public static String getBodyString(BufferedReader br) {
String inputLine;
String str = "";
try {
while ((inputLine = br.readLine()) != null) {
str += inputLine;
}
logger.info("【AuthUserFilter】str: " + str);
String[] split2 = str.split("=");
logger.info("【AuthUserFilter】split2: " + split2);
str = split2[1];
br.close();
} catch (IOException e) {
logger.info("【AuthUserFilter】getBodyString: " + e);
}
return str;
}
private String getEncryptString(String result) {
String encryptStr = null;
try {
if(result.length() > 10000) {//为性能考虑,字符串太长,采用AES加密
encryptStr = AES.encode(result,Constant.APP_AES_PUBLIC_KEY);
}else {
encryptStr = RSAUtils.publicEncrypt(result,RSAUtils.getPublicKey(Constant.APP_RESPONSE_PUBLIC_KEY));
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encryptStr;
}
private Map<String, Object> getDecryptMap(String parameter,String type) {
String decodedData;
Map<String, Object> paramToMap = new HashMap<String, Object>();
try {
decodedData = RSAUtils.privateDecrypt(parameter, RSAUtils.getPrivateKey(Constant.APP_PRIVATE_KEY));
paramToMap = paramToMap(decodedData,type);
// 此处还可以进行其他的相关验证,比如token等------
// 此处还可以进行其他的相关验证,比如token等------
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
e.printStackTrace();
}
return paramToMap;
}
private void writeResponse(ServletResponse response, String responseString) throws IOException {
response.setContentLength(responseString.length());
PrintWriter out = response.getWriter();
out.print(responseString);
out.flush();
out.close();
}
/**
* 设置值参数
*
* @param request
* @param paramToMap
*/
private void setRequestParams(ParameterRequestWrapper request, Map<String, Object> paramToMap) {
if (paramToMap.size() > 0) {
Set<Entry<String, Object>> entrySet = paramToMap.entrySet();
for (Entry<String, Object> entry : entrySet) {
request.addParameter(entry.getKey(), entry.getValue());
}
}
}
@Override
public void destroy() {
}
/**
* 参数转换为map
*
* @param Urlparams
* @param request
* @return
*/
private Map<String, Object> paramToMap(String Urlparams,String type) {
Map<String, Object> paramsMap = new HashMap<>();
// if ("POST".equalsIgnoreCase(type)) {
// paramsMap = (Map)JSON.parse(Urlparams);
// }else {
String params = Urlparams;
if (StringUtils.isNotEmpty(params)) {
String[] split = params.split("&");
if (split.length > 0) {
for (int i = 0; i < split.length; i++) {
String param = split[i];
String[] split2 = param.split("=");
if (split2.length == 2) {
String filterDangerString = filterDangerString(split2[1]);
if (StringUtils.isNotBlank(filterDangerString)) {
paramsMap.put(split2[0], split2[1]);
}
}
}
}
}
// }
//转map{"appUserId":"4","signAppUserId":"d41d8cd98f00b204e9800998ecf8427e","token":"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyODEiLCJpc3MiOiJjbi50cmF3ZSIsImV4cCI6MTUzMzg5MzYyMX0.IqwSL_bzvHfRGfWw3rGvKZEgfi45ZgDUetgwpTWPtSI","type":"app"}
// if (StringUtils.isNotEmpty(params)) {
// String[] split = params.split(",");
// if (split.length > 0) {
// for (int i = 0; i < split.length; i++) {
// String param = split[i];
// String[] split2 = param.split(":");
// if (split2.length == 2) {
// paramsMap.put(split2[0].substring(1, split2[0].length()-1), split2[1].substring(1, split2[1].length()-1));
// }
// }
// }
// }
//转map ?appUserId=4&signAppUserId=d41d8cd98f00b204e9800998ecf8427e
// String params = Urlparams.substring(1);
return paramsMap;
}
/**
* 过滤危险字符
*/
public String filterDangerString(String params) {
if (params == null) {
return null;
}
params = params.replaceAll("\\|", "");
params = params.replaceAll("&", "&");
params = params.replaceAll(";", "");
params = params.replaceAll("@", "");
params = params.replaceAll("'", "");
params = params.replaceAll("\\'", "");
params = params.replaceAll("<", "<");
params = params.replaceAll(">", ">");
params = params.replaceAll("\\(", "");
params = params.replaceAll("\\)", "");
params = params.replaceAll("\\+", "");
params = params.replaceAll("\r", "");
params = params.replaceAll("\n", "");
params = params.replaceAll("script", "");
params = params.replaceAll("'", "");
params = params.replaceAll("\"", "");
params = params.replaceAll(">", "");
params = params.replaceAll("<", "");
params = params.replaceAll("=", "");
params = params.replaceAll("/", "");
return params;
}
/**
* 判断某个字符串是否存在于数组中
*
* @param stringArray
* 原数组
* @param source
* 查找的字符串
* @return 是否找到
*/
public static boolean contains(String[] stringArray, String source) {
// 转换为list
List<String> tempList = Arrays.asList(stringArray);
// 利用list的包含方法,进行判断
if (tempList.contains(source)) {
return true;
} else {
return false;
}
}
}
RAS加密解密:
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.io.IOUtils;
import com.cloopen.rest.sdk.utils.encoder.BASE64Decoder;
import com.cloopen.rest.sdk.utils.encoder.BASE64Encoder;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RSAUtils {
public static final String CHARSET = "UTF-8";
public static final String RSA_ALGORITHM = "RSA";
public static Map<String, String> createKeys(int keySize){
//为RSA算法创建一个KeyPairGenerator对象
KeyPairGenerator kpg;
try{
kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
}catch(NoSuchAlgorithmException e){
throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
}
//初始化KeyPairGenerator对象,密钥长度
kpg.initialize(keySize);
//生成密匙对
KeyPair keyPair = kpg.generateKeyPair();
//得到公钥
Key publicKey = keyPair.getPublic();
String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
//得到私钥
Key privateKey = keyPair.getPrivate();
String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
Map<String, String> keyPairMap = new HashMap<String, String>();
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
return keyPairMap;
}
/**
* 得到公钥
* @param publicKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过X509编码的Key指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
/**
* 得到私钥
* @param privateKey 密钥字符串(经过base64编码)
* @throws Exception
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//通过PKCS#8编码的Key指令获得私钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
return key;
}
/**
* 公钥加密
* @param data
* @param publicKey
* @return
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 私钥解密
* @param data
* @param privateKey
* @return
*/
public static String privateDecrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
}catch(Exception e){
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 私钥加密
* @param data
* @param privateKey
* @return
*/
public static String privateEncrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("加密字符串[" + data + "]时遇到异常", e);
}
}
/**
* 公钥解密
* @param data
* @param publicKey
* @return
*/
public static String publicDecrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
}catch(Exception e){
throw new RuntimeException("解密字符串[" + data + "]时遇到异常", e);
}
}
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
int maxBlock = 0;
if(opmode == Cipher.DECRYPT_MODE){
maxBlock = keySize / 8;
}else{
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try{
while(datas.length > offSet){
if(datas.length-offSet > maxBlock){
buff = cipher.doFinal(datas, offSet, maxBlock);
}else{
buff = cipher.doFinal(datas, offSet, datas.length-offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
}catch(Exception e){
throw new RuntimeException("加解密阀值为["+maxBlock+"]的数据时发生异常", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
public static String AESEncode(String encodeRules,String content){
try {
//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen=KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//生成一个128位的随机源,根据传入的字节数组
keygen.init(128, new SecureRandom(encodeRules.getBytes()));
//3.产生原始对称密钥
SecretKey original_key=keygen.generateKey();
//4.获得原始对称密钥的字节数组
byte [] raw=original_key.getEncoded();
//5.根据字节数组生成AES密钥
SecretKey key=new SecretKeySpec(raw, "AES");
//6.根据指定算法AES自成密码器
Cipher cipher=Cipher.getInstance("AES");
//7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
cipher.init(Cipher.ENCRYPT_MODE, key);
//8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte [] byte_encode=content.getBytes("utf-8");
//9.根据密码器的初始化方式--加密:将数据加密
byte [] byte_AES=cipher.doFinal(byte_encode);
//10.将加密后的数据转换为字符串
//这里用Base64Encoder中会找不到包
//解决办法:
//在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
String AES_encode=new String(new BASE64Encoder().encode(byte_AES));
//11.将字符串返回
return AES_encode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//如果有错就返加nulll
return null;
}
/*
* 解密
* 解密过程:
* 1.同加密1-4步
* 2.将加密后的字符串反纺成byte[]数组
* 3.将加密内容解密
*/
public static String AESDncode(String encodeRules,String content){
try {
//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen=KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//生成一个128位的随机源,根据传入的字节数组
keygen.init(128, new SecureRandom(encodeRules.getBytes()));
//3.产生原始对称密钥
SecretKey original_key=keygen.generateKey();
//4.获得原始对称密钥的字节数组
byte [] raw=original_key.getEncoded();
//5.根据字节数组生成AES密钥
SecretKey key=new SecretKeySpec(raw, "AES");
//6.根据指定算法AES自成密码器
Cipher cipher=Cipher.getInstance("AES");
//7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
cipher.init(Cipher.DECRYPT_MODE, key);
//8.将加密并编码后的内容解码成字节数组
byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
/*
* 解密
*/
byte [] byte_decode=cipher.doFinal(byte_content);
String AES_decode=new String(byte_decode,"utf-8");
return AES_decode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
//如果有错就返加nulll
return null;
}
/***
* MD5加码 生成32位md5码
*/
public static String string2MD5(String inStr){
MessageDigest md5 = null;
try{
md5 = MessageDigest.getInstance("MD5");
}catch (Exception e){
System.out.println(e.toString());
e.printStackTrace();
return "";
}
char[] charArray = inStr.toCharArray();
byte[] byteArray = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++)
byteArray[i] = (byte) charArray[i];
byte[] md5Bytes = md5.digest(byteArray);
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++){
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16)
hexValue.append("0");
hexValue.append(Integer.toHexString(val));
}
return hexValue.toString();
}
/**
* 加密解密算法 执行一次加密,两次解密
*/
public static String convertMD5(String inStr){
char[] a = inStr.toCharArray();
for (int i = 0; i < a.length; i++){
a[i] = (char) (a[i] ^ 't');
}
String s = new String(a);
return s;
}
public static void main (String[] args) throws Exception {
Map<String, String> keyMap = RSAUtils.createKeys(1024);
String publicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
//测试
System.out.println("公钥: \n\r" + publicKey);
System.out.println("私钥: \n\r" + privateKey);
System.out.println("公钥加密——私钥解密");
String str = "123你好";
System.out.println("\r明文:\r\n" + str);
String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey));
System.out.println("密文:\r\n" + encodedData);
String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey));
System.out.println("解密后文字: \r\n" + decodedData);
}
}
package com.example.util;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
public class AES {
static final String algorithmStr = "AES/ECB/PKCS5Padding";
private static final Object TAG = "AES";
static private KeyGenerator keyGen;
static private Cipher cipher;
static boolean isInited = false;
private static void init() {
try {
/**为指定算法生成一个 KeyGenerator 对象。
*此类提供(对称)密钥生成器的功能。
*密钥生成器是使用此类的某个 getInstance 类方法构造的。
*KeyGenerator 对象可重复使用,也就是说,在生成密钥后,
*可以重复使用同一 KeyGenerator 对象来生成进一步的密钥。
*生成密钥的方式有两种:与算法无关的方式,以及特定于算法的方式。
*两者之间的惟一不同是对象的初始化:
*与算法无关的初始化
*所有密钥生成器都具有密钥长度 和随机源 的概念。
*此 KeyGenerator 类中有一个 init 方法,它可采用这两个通用概念的参数。
*还有一个只带 keysize 参数的 init 方法,
*它使用具有最高优先级的提供程序的 SecureRandom 实现作为随机源
*(如果安装的提供程序都不提供 SecureRandom 实现,则使用系统提供的随机源)。
*此 KeyGenerator 类还提供一个只带随机源参数的 inti 方法。
*因为调用上述与算法无关的 init 方法时未指定其他参数,
*所以由提供程序决定如何处理将与每个密钥相关的特定于算法的参数(如果有)。
*特定于算法的初始化
*在已经存在特定于算法的参数集的情况下,
*有两个具有 AlgorithmParameterSpec 参数的 init 方法。
*其中一个方法还有一个 SecureRandom 参数,
*而另一个方法将已安装的高优先级提供程序的 SecureRandom 实现用作随机源
*(或者作为系统提供的随机源,如果安装的提供程序都不提供 SecureRandom 实现)。
*如果客户端没有显式地初始化 KeyGenerator(通过调用 init 方法),
*每个提供程序必须提供(和记录)默认初始化。
*/
keyGen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 初始化此密钥生成器,使其具有确定的密钥长度。
keyGen.init(128); //128位的AES加密
try {
// 生成一个实现指定转换的 Cipher 对象。
cipher = Cipher.getInstance(algorithmStr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
}
//标识已经初始化过了的字段
isInited = true;
}
private static byte[] genKey() {
if (!isInited) {
init();
}
//首先 生成一个密钥(SecretKey),
//然后,通过这个秘钥,返回基本编码格式的密钥,如果此密钥不支持编码,则返回 null。
return keyGen.generateKey().getEncoded();
}
private static byte[] encrypt(byte[] content, byte[] keyBytes) {
byte[] encryptedText = null;
if (!isInited) {
init();
}
/**
*类 SecretKeySpec
*可以使用此类来根据一个字节数组构造一个 SecretKey,
*而无须通过一个(基于 provider 的)SecretKeyFactory。
*此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密钥有用
*构造方法根据给定的字节数组构造一个密钥。
*此构造方法不检查给定的字节数组是否指定了一个算法的密钥。
*/
Key key = new SecretKeySpec(keyBytes, "AES");
try {
// 用密钥初始化此 cipher。
cipher.init(Cipher.ENCRYPT_MODE, key);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
try {
//按单部分操作加密或解密数据,或者结束一个多部分操作。(不知道神马意思)
encryptedText = cipher.doFinal(content);
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptedText;
}
private static byte[] encrypt(String content, String password) {
try {
byte[] keyStr = getKey(password);
SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
byte[] byteContent = content.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// ʼ
byte[] result = cipher.doFinal(byteContent);
return result; //
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
private static byte[] decrypt(byte[] content, String password) {
try {
byte[] keyStr = getKey(password);
SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
cipher.init(Cipher.DECRYPT_MODE, key);// ʼ
byte[] result = cipher.doFinal(content);
return result; //
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
private static byte[] getKey(String password) {
byte[] rByte = null;
if (password!=null) {
rByte = password.getBytes();
}else{
rByte = new byte[24];
}
return rByte;
}
/**
* 将二进制转换成16进制
* @param buf
* @return
*/
public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
/**
* 将16进制转换为二进制
* @param hexStr
* @return
*/
public static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1)
return null;
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; i++) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
//注意: 这里的password(秘钥必须是16位的)
private static final String keyBytes = "abcdefgabcdefg12";
/**
*加密
*/
public static String encode(String content,String keyBytes){
//加密之后的字节数组,转成16进制的字符串形式输出
return parseByte2HexStr(encrypt(content, keyBytes));
}
/**
*解密
*/
public static String decode(String content,String keyBytes){
//解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入
byte[] b = decrypt(parseHexStr2Byte(content), keyBytes);
return new String(b);
}
//测试用例
public static void test1(){
long start = System.currentTimeMillis();
String content = "{\"data\":[{\"cityId\":0,\"count\":0,\"id\":0,\"maxAmount\":0,\"ownerCode\":0,\"provinceId\":41,\"provinceName\":\"河南省\",\"tag\":0,\"valid\":0,\"vehicleColor\":0,\"vehicleLicColor\":0,\"withholdStatus\":0},{\"cityId\":0,\"count\":0,\"id\":0,\"maxAmount\":0,\"ownerCode\":0,\"provinceId\":61,\"provinceName\":\"陕西省\",\"tag\":0,\"valid\":0,\"vehicleColor\":0,\"vehicleLicColor\":0,\"withholdStatus\":0},{\"cityId\":0,\"count\":0,\"id\":0,\"maxAmount\":0,\"ownerCode\":0,\"provinceId\":43,\"provinceName\":\"湖南省\",\"tag\":0,\"valid\":0,\"vehicleColor\":0,\"vehicleLicColor\":0,\"withholdStatus\":0},{\"cityId\":0,\"count\":0,\"id\":0,\"maxAmount\":0,\"ownerCode\":0,\"provinceId\":36,\"provinceName\":\"江西省\",\"tag\":0,\"valid\":0,\"vehicleColor\":0,\"vehicleLicColor\":0,\"withholdStatus\":0}],\"message\":\"成功\",\"status\":1}";
String key = "JvcaUK7cG8mGOPcDvK1BFMXI93skTA1C";
String pStr = encode(content,key );
// System.out.println("加密前:"+content);
// System.out.println("加密后:" + pStr);
String postStr = decode(pStr,key );
// System.out.println("解密后:"+ postStr );
long end = System.currentTimeMillis();
System.out.println("yiyiyi time: "+(end-start));
}
public static void main(String[] args) {
test1();
}
}