package com.app.pay.common.util;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.ods.common.util.Base64Util;
/**
* @FileName AESUtil.java
* @Description:
*
* @Date 2019年2月13日
* @author pangxianhe
*
*/
public class AESUtil {
//加密方式
public static String KEY_ALGORITHM = "AES";
//數據填充方式
public static String algorithmStr = "AES/CBC/PKCS5Padding";
//避免重複new生成多個BouncyCastleProvider對象,因爲GC回收不了,會造成內存溢出
//只在第一次調用decrypt()方法時才new 對象
public static boolean initialized = false;
/**
* 加密
* @param content
* @param Key
* @param ivStr
* @return
* @author pangxianhe
* @date 2019年2月13日
*/
public static String encrypt(String content, String Key, String ivStr) {
initialize();
try {
Cipher cipher = Cipher.getInstance(algorithmStr);
SecretKeySpec skeySpec = new SecretKeySpec(Key.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivStr.getBytes()));
byte[] encrypted = cipher.doFinal(content.getBytes());
return Base64Util.encode(encrypted);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 解密
* @param content
* @param aesKey
* @param iv
* @return
* @author pangxianhe
* @date 2019年2月13日
*/
public static String decrypt(String content, String aesKey, String iv) {
initialize();
try {
byte[] encrypted1 = Base64Util.decode(content);//先用base64解密
Cipher cipher = Cipher.getInstance(algorithmStr);
Key sKeySpec = new SecretKeySpec(aesKey.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(iv.getBytes()));// 初始化
byte[] result = cipher.doFinal(encrypted1);
String originalString = new String(result);
return originalString;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**BouncyCastle作爲安全提供,防止我們加密解密時候因爲jdk內置的不支持改模式運行報錯。**/
public static void initialize() {
if (initialized)
return;
Security.addProvider(new BouncyCastleProvider());
initialized = true;
}
// 生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
public static void main(String[] args) throws Exception {
/*
* 加密用的Key 可以用26個字母和數字組成,最好不要用保留字符,雖然不會錯,至於怎麼裁決,個人看情況而定
* 此處使用AES-128-CBC加密模式,key需要爲16位。
*/
// 需要加密的字串
String cSrc = "{data:[{'name':'你好','age':20},{'name':'zd','age':18}]}";
String cKey = "qwqw1234qwqw1234qwqw1234szqwqw12";
String vi = "0000000000000000";
System.out.println(cSrc);
// 加密
long lStart = System.currentTimeMillis();
String enString = AESUtil.encrypt(cSrc, cKey,vi);
System.out.println("加密後的字串是:" + enString);
long lUseTime = System.currentTimeMillis() - lStart;
System.out.println("加密耗時:" + lUseTime + "毫秒");
// 解密
lStart = System.currentTimeMillis();
String DeString = AESUtil.decrypt(enString, cKey,vi);
System.out.println("解密後的字串是:" + DeString);
lUseTime = System.currentTimeMillis() - lStart;
System.out.println("解密耗時:" + lUseTime + "毫秒");
}
}
此處加密的key是qwqw1234qwqw1234
,如果修改爲32位或者更高位的的將會報java.security.InvalidKeyException: Illegal key size
解決辦法:
下載對應的jar文件替換原有的,
jdk1.8的http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html。
其他版本的與之類似,下載好後解壓,主要用到local_policy.jar和US_export_policy.jar,將其複製到JAVA_HOME下的\jre\lib\security中替換,即可