| | |
| | | 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 org.springframework.util.StringUtils; |
| | | |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | |
| | | /** |
| | | * AES加密解密 |
| | | * |
| | | * @author wd |
| | | */ |
| | | public class SecurityUtil { |
| | | |
| | | private SecurityUtil() { |
| | | } |
| | | |
| | | /** |
| | | * AES加密 |
| | |
| | | * @return 密文 |
| | | */ |
| | | public static String encryptAES(String content, String secretKey) { |
| | | checkParam(content,secretKey); |
| | | checkParam(content, secretKey); |
| | | //AES加密 |
| | | String encryptResultStr = encrypt(content, secretKey); |
| | | //BASE64位加密 |
| | | encryptResultStr = ebotongEncrypto(encryptResultStr); |
| | | return encryptResultStr; |
| | | return encrypt(content, secretKey); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param encryptResultStr 密文 |
| | | * @return 明文 |
| | | */ |
| | | public static String decryptAES(String encryptResultStr,String secretKey) { |
| | | checkParam(encryptResultStr,secretKey); |
| | | public static String decryptAES(String encryptResultStr, String secretKey) { |
| | | checkParam(encryptResultStr, secretKey); |
| | | try { |
| | | // BASE64位解密 |
| | | String decrpt = ebotongDecrypto(encryptResultStr); |
| | | byte[] decryptFrom = hexToByteArray(decrpt); |
| | | byte[] decryptFrom = Base64.getDecoder().decode(encryptResultStr); |
| | | |
| | | //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)) { |
| | | private static void checkParam(String encryptResultStr, String secretKey) { |
| | | if (StringUtils.isEmpty(encryptResultStr)) { |
| | | throw new BusinessException(ErrorCode.CONTENT_EMPTY_ERROR); |
| | | } |
| | | if (isBlank(secretKey)) { |
| | | throw new BusinessException(ErrorCode.SECRET_KEY_ERROR); |
| | | } |
| | | // if (secretKey.length() != CimsConstants.SECRET_KEY_LENGTH || !secretKey.matches(CimsConstants.SECRET_KEY_REGEX)) { |
| | | // throw new BusinessException(ErrorCode.SECRET_KEY_ERROR); |
| | | // } |
| | | if (!secretKey.matches(CimsConstants.SECRET_KEY_REGEX)) { |
| | | throw new BusinessException(ErrorCode.SECRET_KEY_ERROR); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 加密 |
| | | * |
| | | * @param content 需要加密的内容 |
| | | * @param password 加密密码 |
| | | * @param content 需要加密的内容 |
| | | * @param secretKey 加密密钥 |
| | | * @return |
| | | */ |
| | | private static String encrypt(String content, String password) { |
| | | private static String encrypt(String content, String secretKey) { |
| | | 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(); |
| | | byte[] raw = secretKey.getBytes(CimsConstants.SECRET_KEY_ENCODING); |
| | | SecretKeySpec keySpec = new SecretKeySpec(raw, "AES"); |
| | | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//NOSONAR sonar扫描忽略这段代码 |
| | | cipher.init(Cipher.ENCRYPT_MODE, keySpec); |
| | | byte[] bytes = cipher.doFinal(content.getBytes(CimsConstants.SECRET_KEY_ENCODING)); |
| | | return Base64.getEncoder().encodeToString(bytes); |
| | | } catch (Exception e) { |
| | | throw new BusinessException(ErrorCode.CONTENT_ENCODE_ERROR); |
| | | } |
| | |
| | | /** |
| | | * 解密 |
| | | * |
| | | * @param content 待解密内容 |
| | | * @param password 解密密钥 |
| | | * @param content 待解密内容 |
| | | * @param secretKey 解密密钥 |
| | | * @return |
| | | */ |
| | | private static byte[] decrypt(byte[] content, String password) { |
| | | private static byte[] decrypt(byte[] content, String secretKey) { |
| | | 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; |
| | | byte[] raw = secretKey.getBytes(CimsConstants.SECRET_KEY_ENCODING); |
| | | SecretKeySpec keySpec = new SecretKeySpec(raw, "AES"); |
| | | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//NOSONAR sonar扫描忽略这段代码 |
| | | cipher.init(Cipher.DECRYPT_MODE, keySpec); |
| | | return cipher.doFinal(content); |
| | | } 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; |
| | | } |
| | | |
| | | } |