import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/**
* AES 加密解密
*/
public class AESUtil {
/**
* 可选的模式
*/
public static final String CBC_PKCS5Padding = "AES/CBC/PKCS5Padding";
public static final String CFB_NoPadding = "AES/CFB/NoPadding";
public static final String OFB_NoPadding = "AES/OFB/NoPadding";
public static final String CTR_NoPadding = "AES/CTR/NoPadding";
public static final String GCM_NoPadding = "AES/GCM/NoPadding";
/**
* 加密
*/
public static String encryptWithIv(String mode, String data, SecretKey key, IvParameterSpec iv) throws Exception {
Cipher cipher = Cipher.getInstance(mode);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
return bytesToHex(cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)));
}
/**
* 解密
*/
public static String decryptWithIv(String mode, String data, SecretKey key, IvParameterSpec iv) throws Exception {
Cipher cipher = Cipher.getInstance(mode);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
return bytesToString(cipher.doFinal(hexToBytes(data)));
}
/**
* 字符串转字节数组
*/
public static byte[] stringToBytes(String data) {
return data.getBytes(StandardCharsets.UTF_8);
}
/**
* 字节数组转字符串
*/
public static String bytesToString(byte[] data) {
return new String(data);
}
/**
* 字节数组转base64字符串
*/
public static String bytesToBase64(byte[] data) {
return Base64.getEncoder().encodeToString(data);
}
/**
* 字符串转base64字节数组
*/
public static byte[] base64ToBytes(String data) {
return Base64.getDecoder().decode(data);
}
/**
* 字节数组转16进制字符串
*/
public static String bytesToHex(byte[] data) {
return new BigInteger(1, data).toString(16);
}
/**
* 字符串转16进制字节数组
*/
public static byte[] hexToBytes(String data) {
byte[] byteArray = new BigInteger(data, 16).toByteArray();
if (byteArray[0] == 0) {
byte[] output = new byte[byteArray.length - 1];
System.arraycopy(byteArray, 1, output, 0, output.length);
return output;
}
return byteArray;
}
/**
* 生成 AES 密钥,n 可选:128、192、256
*/
public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(n);
return keyGenerator.generateKey();
}
/**
* 生成 AES 初始向量 IV
*/
public static IvParameterSpec generateIV() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
public static void main(String[] args) throws Exception {
// 此处防止每次调用加密时都new BouncyCastleProvider对象,否则会发生内存泄露,这里只针对GCM模式
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
Security.addProvider(new BouncyCastleProvider());
}
String data = "AES算法";
// 1.生成随机iv和key
IvParameterSpec iv = generateIV();
SecretKey key = generateKey(128);
System.out.println("key: " + bytesToHex(key.getEncoded()));
System.out.println("iv: " + bytesToHex(iv.getIV()));
String encrypt = encryptWithIv(CFB_NoPadding, data, key, iv);
System.out.println("加密后 encrypt: " + encrypt);
String decrypt = decryptWithIv(CFB_NoPadding, encrypt, key, iv);
System.out.println("解密后 decrypt: " + decrypt);
// 2.固定iv和key
IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes("8ceaa3c7039c0ad61f17ce44a30cf326"));
SecretKeySpec keySpec = new SecretKeySpec(stringToBytes("237541348a7894d20e42e6222a7caef3"), "AES");
String encrypt1 = encryptWithIv(GCM_NoPadding, data, keySpec, ivSpec);
System.out.println("加密后 encrypt: " + encrypt1);
String decrypt1 = decryptWithIv(GCM_NoPadding, encrypt1, keySpec, ivSpec);
System.out.println("解密后 decrypt: " + decrypt1);
}
}
AES加解密
于 2022-11-23 15:22:28 首次发布