package com.iplatform.core.util; import com.walker.infrastructure.utils.Base64; import com.walker.infrastructure.utils.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Security; import java.util.Arrays; /** * AES对称加密、解密工具。 * @author 时克英 * @date 2023-06-15 */ public class AESUtils { private static final String AES_ALGORITHM = "AES"; private static final String UTF8 = StandardCharsets.UTF_8.name(); // 微信解密手机号使用,2023-09-15 // static { // Security.addProvider(new BouncyCastleProvider()); // } /* AES加密 String */ public static String encryptStrAES(String text, String key){ if(!StringUtils.hasLength(text)){ throw new IllegalStateException("encode text should not be null or empty."); } byte[] encodeBytes = encryptByteAES(text.getBytes(StandardCharsets.UTF_8), key); // return Base64.encodeBase64String(encodeBytes); return new String(Base64.encodeBase64(encodeBytes)); } /* AES解密 String*/ public static String decryptStrAES(String text, String key){ if(!StringUtils.hasLength(text)){ throw new IllegalStateException("decode text should not be null or empty."); } byte[] decoded = Base64.decode(text.getBytes(StandardCharsets.UTF_8)); // byte[] decodeBytes = decryptByteAES(Base64.decodeBase64(text.getBytes(StandardCharsets.UTF_8)), key); byte[] decodeBytes = decryptByteAES(decoded, key); return new String(decodeBytes, StandardCharsets.UTF_8); } /* AES加密 originalBytes */ public static byte[] encryptByteAES(byte[] originalBytes, String key){ if(originalBytes == null || originalBytes.length == 0){ throw new IllegalStateException("encode originalBytes should not be empty."); } if(!StringUtils.hasLength(key)){ throw new IllegalStateException("key :" + key + ", encode key should not be null or empty."); } Cipher cipher = getAESCipher(key, Cipher.ENCRYPT_MODE); byte[] encodeBytes = null; try { encodeBytes = cipher.doFinal(originalBytes); } catch (IllegalBlockSizeException | BadPaddingException e) { throw new IllegalStateException(e.getClass().getName()+": encode byte fail. "+e.getMessage()); } return encodeBytes; } /* AES解密 encryptedBytes */ public static byte[] decryptByteAES(byte[] encryptedBytes, String key){ if(encryptedBytes == null || encryptedBytes.length == 0){ throw new IllegalStateException("decode encryptedBytes should not be empty."); } if(!StringUtils.hasLength(key)){ throw new IllegalStateException("key :" + key + ", decode key should not be null or empty."); } Cipher cipher = getAESCipher(key, Cipher.DECRYPT_MODE); byte[] decodeBytes = null; try { decodeBytes = cipher.doFinal(encryptedBytes); } catch (IllegalBlockSizeException | BadPaddingException e) { throw new IllegalStateException(e.getClass().getName()+": decode byte fail. "+e.getMessage()); } return decodeBytes; } public static Cipher getAESCipher(String key, int mode){ if(!StringUtils.hasLength(key)){ throw new IllegalStateException("key :" + key + ", should not be null or empty."); } Cipher cipher = null; SecretKey secretKey; try { cipher = Cipher.getInstance(AES_ALGORITHM); byte[] keyBytes = key.getBytes(UTF8); secretKey = new SecretKeySpec(keyBytes, AES_ALGORITHM); cipher.init(mode, secretKey); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new IllegalStateException(e.getClass().getName()+": get cipher instance wrong. "+e.getMessage()); } catch (UnsupportedEncodingException u){ throw new IllegalStateException(u.getClass().getName()+": key transfer bytes fail. "+u.getMessage()); } catch (InvalidKeyException i) { throw new IllegalStateException(i.getClass().getName()+": key is invalid. "+i.getMessage()); } return cipher; } /** * AES解密,目前微信解密授权手机号使用。 * * @param content * 密文 * @return * @throws InvalidAlgorithmParameterException * @throws NoSuchProviderException * @date 2023-09-15 */ public static final byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { initialize(); // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 // int base = 16; // if (ivByte.length % base != 0) { // int groups = ivByte.length / base + (ivByte.length % base != 0 ? 1 : 0); // byte[] temp = new byte[groups * base]; // Arrays.fill(temp, (byte) 0); // System.arraycopy(ivByte, 0, temp, 0, ivByte.length); // ivByte = temp; // } try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); Key sKeySpec = new SecretKeySpec(keyByte, AES_ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化 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(); } catch (NoSuchProviderException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } // 生成iv public static AlgorithmParameters generateIV(byte[] iv) throws Exception { AlgorithmParameters params = AlgorithmParameters.getInstance(AES_ALGORITHM); params.init(new IvParameterSpec(iv)); return params; } public static void initialize() { if (initialized) return; Security.addProvider(new BouncyCastleProvider()); initialized = true; } public static boolean initialized = false; public static final String KEY_16 = "954327510putvwmz"; // public static final String KEY_8 = "95432puz"; public static void main(String[] args) { // String msg = "商户号=adf0099ogglk11wweedcvfg"; // System.out.println("AES秘钥长度只能为16、24、32:"+KEY_16.getBytes(StandardCharsets.UTF_8).length); // String s = encryptStrAES(msg, KEY_16); // System.out.println("加密后:"+s); // String s1 = decryptStrAES(s, KEY_16); // System.out.println("解密后:"+s1); String encrypt = "epFJjFcG1VY/3NrhhPBKvA=="; System.out.println("解密数据:" + AESUtils.decryptStrAES(encrypt, KEY_16)); } }