Java AES-256 加密实现
AES-256 是一种对称加密算法,使用 256 位密钥,以下是 Java 中实现 AES-256 加密和解密的完整示例。

基本实现
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class AES256Util {
// 算法名称
private static final String ALGORITHM = "AES";
// 加密模式/填充方式
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
// IV长度 (AES块大小是128位)
private static final int IV_LENGTH = 16;
// 密钥长度 (AES-256需要32字节)
private static final int KEY_LENGTH = 256;
/**
* 生成AES-256密钥
*/
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(KEY_LENGTH);
return keyGenerator.generateKey();
}
/**
* 从字节数组创建密钥
*/
public static SecretKey getKeyFromBytes(byte[] keyBytes) {
return new SecretKeySpec(keyBytes, ALGORITHM);
}
/**
* 从Base64字符串创建密钥
*/
public static SecretKey getKeyFromString(String keyString) {
byte[] keyBytes = Base64.getDecoder().decode(keyString);
return getKeyFromBytes(keyBytes);
}
/**
* 生成随机IV
*/
public static byte[] generateIv() {
byte[] iv = new byte[IV_LENGTH];
new SecureRandom().nextBytes(iv);
return iv;
}
/**
* 加密
*/
public static String encrypt(String data, SecretKey key, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, ivParameterSpec);
byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
// 将IV和加密数据合并 (IV不需要保密,但需要与密文一起保存)
byte[] combined = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, combined, 0, iv.length);
System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(combined);
}
/**
* 解密
*/
public static String decrypt(String encryptedData, SecretKey key) throws Exception {
byte[] combined = Base64.getDecoder().decode(encryptedData);
// 提取IV (前16字节)
byte[] iv = new byte[IV_LENGTH];
System.arraycopy(combined, 0, iv, 0, iv.length);
// 提取加密数据 (剩余字节)
byte[] encrypted = new byte[combined.length - iv.length];
System.arraycopy(combined, iv.length, encrypted, 0, encrypted.length);
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, key, ivParameterSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, StandardCharsets.UTF_8);
}
public static void main(String[] args) throws Exception {
// 生成密钥
SecretKey key = generateKey();
String keyString = Base64.getEncoder().encodeToString(key.getEncoded());
System.out.println("生成的密钥: " + keyString);
// 生成IV
byte[] iv = generateIv();
// 原始数据
String originalData = "这是一个需要加密的敏感信息";
System.out.println("原始数据: " + originalData);
// 加密
String encrypted = encrypt(originalData, key, iv);
System.out.println("加密后: " + encrypted);
// 解密
String decrypted = decrypt(encrypted, key);
System.out.println("解密后: " + decrypted);
}
}
使用固定密钥的简化版本
如果需要使用固定的密钥(不推荐用于生产环境,仅用于演示):
public class AES256FixedKeyExample {
private static final String FIXED_KEY = "ThisIsA32ByteLongFixedKey123"; // 必须是32字节长度
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String data) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(FIXED_KEY.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
// 生成随机IV
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
// 合并IV和密文
byte[] combined = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, combined, 0, iv.length);
System.arraycopy(encrypted, 0, combined, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(combined);
}
public static String decrypt(String encryptedData) throws Exception {
byte[] combined = Base64.getDecoder().decode(encryptedData);
// 提取IV
byte[] iv = new byte[16];
System.arraycopy(combined, 0, iv, 0, iv.length);
// 提取密文
byte[] encrypted = new byte[combined.length - 16];
System.arraycopy(combined, 16, encrypted, 0, encrypted.length);
SecretKeySpec keySpec = new SecretKeySpec(FIXED_KEY.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance(ALGORITHM);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, StandardCharsets.UTF_8);
}
}
注意事项
- 密钥管理:生产环境中不应硬编码密钥,应使用密钥管理系统或从安全位置加载
- IV处理:IV不需要保密,但必须与密文一起保存,且每次加密应使用不同的IV
- 填充方式:PKCS5Padding是常用的填充方式,确保数据长度是AES块大小的整数倍
- 异常处理:实际应用中应妥善处理所有可能的异常
- 性能考虑:对于大量数据,考虑使用流式加密而非一次性加密整个数据
推荐的密钥存储方式
对于生产环境,建议:
// 从环境变量或配置文件中读取密钥
String keyFromConfig = System.getenv("AES_ENCRYPTION_KEY");
SecretKey key = AES256Util.getKeyFromString(keyFromConfig);
确保密钥存储在安全的位置,如密钥管理服务、环境变量或加密的配置文件中。

