package cn.gistack.system.user.sync.util;
|
|
|
import cn.gistack.system.user.sync.constant.CimsConstants;
|
import cn.gistack.system.user.sync.exception.BusinessException;
|
import cn.gistack.system.user.sync.exception.ErrorCode;
|
|
import javax.crypto.Cipher;
|
import javax.crypto.spec.SecretKeySpec;
|
|
/**
|
* AES加密解密
|
* @author wd
|
*/
|
public class SecurityUtil {
|
|
/**
|
* AES加密
|
*
|
* @param content 明文
|
* @return 密文
|
*/
|
public static String encryptAES(String content, String secretKey) {
|
checkParam(content,secretKey);
|
//AES加密
|
String encryptResultStr = encrypt(content, secretKey);
|
//BASE64位加密
|
encryptResultStr = ebotongEncrypto(encryptResultStr);
|
return encryptResultStr;
|
}
|
|
/**
|
* AES解密
|
*
|
* @param encryptResultStr 密文
|
* @return 明文
|
*/
|
public static String decryptAES(String encryptResultStr,String secretKey) {
|
checkParam(encryptResultStr,secretKey);
|
try {
|
// BASE64位解密
|
String decrpt = ebotongDecrypto(encryptResultStr);
|
byte[] decryptFrom = hexToByteArray(decrpt);
|
//AES解密
|
byte[] decryptResult = decrypt(decryptFrom, secretKey);
|
return new String(decryptResult);
|
} catch (Exception e) {
|
e.printStackTrace();
|
// 当密文不规范时会报错,可忽略,但调用的地方需要考虑
|
throw new BusinessException(ErrorCode.CONTENT_EMPTY_ERROR);
|
}
|
}
|
|
/**
|
* 校验参数
|
*/
|
private static void checkParam(String encryptResultStr,String secretKey){
|
if (isBlank(encryptResultStr)) {
|
throw new BusinessException(ErrorCode.CONTENT_EMPTY_ERROR);
|
}
|
if (secretKey.length() != CimsConstants.SECRET_KEY_LENGTH || !secretKey.matches(CimsConstants.SECRET_KEY_REGEX)) {
|
throw new BusinessException(ErrorCode.SECRET_KEY_ERROR);
|
}
|
}
|
|
|
/**
|
* 加密
|
*
|
* @param content 需要加密的内容
|
* @param password 加密密码
|
* @return
|
*/
|
private static String encrypt(String content, String password) {
|
try {
|
byte[] raw = password.getBytes(CimsConstants.SECRET_KEY_ENCODING);
|
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
|
byte[] byteRresult = cipher.doFinal(content.getBytes(CimsConstants.SECRET_KEY_ENCODING));
|
StringBuffer sb = new StringBuffer();
|
for (int i = 0; i < byteRresult.length; i++) {
|
String hex = Integer.toHexString(byteRresult[i] & 0xFF);
|
if (hex.length() == 1) {
|
hex = '0' + hex;
|
}
|
sb.append(hex.toUpperCase());
|
}
|
return sb.toString();
|
} catch (Exception e) {
|
throw new BusinessException(ErrorCode.CONTENT_ENCODE_ERROR);
|
}
|
}
|
|
/**
|
* 解密
|
*
|
* @param content 待解密内容
|
* @param password 解密密钥
|
* @return
|
*/
|
private static byte[] decrypt(byte[] content, String password) {
|
try {
|
byte[] raw = password.getBytes(CimsConstants.SECRET_KEY_ENCODING);
|
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
|
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
|
byte[] result = cipher.doFinal(content);
|
return result;
|
} catch (Exception e) {
|
e.printStackTrace();
|
throw new BusinessException(ErrorCode.SECRET_DECODE_ERROR);
|
}
|
}
|
|
/**
|
* hex字符串转byte数组
|
* @param inHex 待转换的Hex字符串
|
* @return 转换后的byte数组结果
|
*/
|
private static byte[] hexToByteArray(String inHex){
|
int hexlen = inHex.length();
|
byte[] result;
|
if (hexlen % 2 == 1){
|
//奇数
|
hexlen++;
|
result = new byte[(hexlen/2)];
|
inHex="0"+inHex;
|
}else {
|
//偶数
|
result = new byte[(hexlen/2)];
|
}
|
int j=0;
|
for (int i = 0; i < hexlen; i+=2){
|
result[j] = hexToByte(inHex.substring(i,i+2));
|
j++;
|
}
|
return result;
|
}
|
|
/**
|
* Hex字符串转byte
|
* @param inHex 待转换的Hex字符串
|
* @return 转换后的byte
|
*/
|
private static byte hexToByte(String inHex){
|
return (byte)Integer.parseInt(inHex,16);
|
}
|
|
/**
|
* Base64加密字符串
|
*/
|
private static String ebotongEncrypto(String str) {
|
String result = str;
|
if (str != null && str.length() > 0) {
|
try {
|
byte[] encodeByte = str.getBytes(CimsConstants.SECRET_KEY_ENCODING);
|
result = Base64.getEncoder().encodeToString(encodeByte);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
// base64加密超过一定长度会自动换行 需要去除换行符
|
return result.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
|
}
|
|
/**
|
* Base64解密字符串
|
*/
|
private static String ebotongDecrypto(String str) {
|
byte[] encodeByte = Base64.getDecoder().decode(str);
|
return new String(encodeByte);
|
}
|
|
/**
|
* 判断字符串是否为空
|
* @param cs
|
* @return
|
*/
|
private static boolean isBlank(final CharSequence cs) {
|
int strLen;
|
if (cs == null || (strLen = cs.length()) == 0) {
|
return true;
|
}
|
for (int i = 0; i < strLen; i++) {
|
if (!Character.isWhitespace(cs.charAt(i))) {
|
return false;
|
}
|
}
|
return true;
|
}
|
|
}
|