目录
一、项目背景与介绍
在数据传输和存储过程中,保护敏感信息的安全性非常关键。AES(Advanced Encryption Standard,高级加密标准)是一种广泛使用的对称加密算法,具有高效、安全、易于实现等特点。由于 AES 使用同一个密钥进行加密和解密,因此密钥的管理非常重要。
二、相关知识
2.1 AES 加密算法
- 对称加密:AES 算法属于对称加密算法,即加密和解密使用相同的密钥。其优点是速度快,适合大数据量加密;缺点是密钥传输和管理存在一定风险。
- 加密模式与填充方式:常用的模式有 ECB、CBC、CFB 等,本示例采用 CBC 模式。由于 AES 的块大小为 16 字节,当明文长度不是 16 字节的整数倍时,需要采用填充方式,本示例采用 PKCS5Padding。
- 初始向量(IV):在 CBC 模式下,初始向量用于增加加密随机性,通常需要随机生成并与密文一起存储。但本示例为了简化演示,使用了固定的 IV(仅供学习参考)。
2.2 Java 加密 API
Java 提供了一整套加密相关的类:
- Cipher:核心加密解密类,用于执行加密和解密操作。
- SecretKeySpec:将原始密钥数据封装为密钥对象。
- IvParameterSpec:封装初始向量数据。
- Base64:用于将二进制数据转换为可读的字符串格式,便于传输和存储。
三、项目实现思路
本项目主要分为以下几个步骤:
- 准备密钥和初始向量:定义 AES 加密所需的 128 位密钥和 16 字节的初始向量(IV)。在实际应用中,这些应由安全随机数生成器产生,并妥善管理。
- 创建 Cipher 对象:使用
Cipher.getInstance("AES/CBC/PKCS5Padding")
获取 Cipher 对象,并分别用密钥和 IV 初始化加密和解密模式。 - 执行加密和解密操作:
- 加密:将明文字符串转换为字节数组,调用
doFinal()
方法获得密文字节数组,再进行 Base64 编码。 - 解密:将 Base64 解码后的密文字节数组通过
doFinal()
方法还原为明文字节数组,并转换为字符串。
- 加密:将明文字符串转换为字节数组,调用
- 整合代码并测试:将上述流程封装到一个 Java 类中,在主函数中调用加密和解密方法,验证加解密是否正确。
四、完整代码实现
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.util.Base64;
public class AESEncryptionDemo {
private static final String KEY = "0123456789abcdef";
private static final String IV = "abcdefghijklmnop";
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String plainText) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(encryptedBytes);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String decrypt(String cipherText) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes("UTF-8"), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decodedBytes = Base64.getDecoder().decode(cipherText);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String plainText = "Hello, AES Encryption!";
System.out.println("原始明文: " + plainText);
String encryptedText = encrypt(plainText);
System.out.println("加密后的密文 (Base64 编码): " + encryptedText);
String decryptedText = decrypt(encryptedText);
System.out.println("解密后的明文: " + decryptedText);
}
}
五、代码解读
5.1 密钥和初始向量设置
- KEY 和 IV:本示例中密钥和初始向量均为固定字符串,长度均为 16 字节,适用于 AES-128。实际应用中应使用安全随机数生成密钥和 IV,并对 IV 进行传输或存储(例如,将 IV 附加在密文中一起传输)。
5.2 加密过程
- Cipher 获取与初始化:使用
Cipher.getInstance("AES/CBC/PKCS5Padding")
获取 Cipher 对象,并利用SecretKeySpec
和IvParameterSpec
初始化 Cipher 为加密模式。 - 数据加密:将明文转换为字节数组后调用
doFinal()
方法进行加密,生成密文字节数组;之后使用 Base64 编码便于输出和存储。
5.3 解密过程
- Cipher 初始化为解密模式:同样使用
SecretKeySpec
和IvParameterSpec
初始化 Cipher 为解密模式。 - 数据解密:将 Base64 解码后的密文字节数组传入
doFinal()
方法进行解密,还原出原始明文字节数组,再转换为字符串。
5.4 异常处理
- 在加密和解密过程中均使用 try-catch 捕获可能出现的异常,并输出堆栈信息,确保程序调试和排查问题时能获得足够的信息。
六、项目总结与展望
本项目通过 Java 实现了 AES 加密和解密的基本流程,主要收获和体会包括:
- 掌握对称加密基本原理,学习了如何使用同一密钥对数据进行加密和解密,并理解了 AES 加密中密钥与初始向量的重要性。
- 熟悉 Java 加密 API,通过 Cipher、SecretKeySpec、IvParameterSpec 等类的使用,掌握了 Java 内置加密工具的基本操作。
- 在实际应用中应采用随机 IV 并妥善管理密钥,确保数据加密安全性。
- 可改进为生成随机 IV,并将 IV 与密文组合(例如,将 IV 前置于密文中一起传输);可以使用更高位数的 AES 加密(如 AES-256),前提是环境支持;将加密/解密过程封装为工具类,便于在实际项目中复用和集成。