Cipher
是 Java 加密框架的一部分,提供了加密和解密操作的核心功能。Cipher.getInstance(String transformation)
:- 用来获取一个加密算法实例。
- 参数
transformation
指定了加密算法的详细配置。
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
这段代码的作用是初始化一个加密/解密工具,使用 AES 算法结合 CBC 模式和 PKCS5Padding 填充方式。
AES/CBC/PKCS5Padding
是一个 transformation,由三部分组成:
(1) AES
- 代表 AES(Advanced Encryption Standard,高级加密标准)。
- 一种对称加密算法,广泛应用于安全通信。
- 数据块长度固定为 128 位(16 字节)。
(2) CBC
- 代表 Cipher Block Chaining(密码块链接模式)。
- 特点:
- 每个加密块与前一个加密块的结果相关联。
- 第一个块需要一个随机的 初始化向量(IV)。
- 优点:
- 提高安全性,同样的明文输入生成的密文不同。
- 注意事项:
- IV 必须是随机生成且长度为 16 字节。
- IV 通常需要与密文一起存储或传输,供解密时使用。
(3) PKCS5Padding
- 代表 填充方式。
- 数据块加密需要满足长度为算法要求的整数倍(AES 为 16 字节),如果数据不足,需要填充。
- PKCS5Padding 的填充规则:
- 在明文后填充一定数量的字节,填充值等于填充的字节数。
- 例如:明文长度为 13 字节,缺 3 字节,则填充
03 03 03
。
1. 常见的加密算法
算法 | 描述 |
---|---|
AES | 高级加密标准,块大小固定为 128 位,密钥长度为 128、192 或 256 位。 |
DES | 数据加密标准,块大小为 64 位,但已过时,不推荐使用。 |
3DES | 三重 DES,比 DES 更安全,但速度较慢,也逐渐被淘汰。 |
RSA | 非对称加密算法,用于加密小数据块或交换密钥。 |
ChaCha20 | 高性能流加密算法,适合现代系统。 |
2. 常见的加密模式
模式 | 描述 |
---|---|
ECB | 电子密码本模式(Electronic Codebook),简单但不安全,相同明文块会生成相同密文块,不推荐。 |
CBC | 密码块链接模式(Cipher Block Chaining),需要初始化向量(IV),安全性高,推荐用于文件加密。 |
CFB | 密码反馈模式(Cipher Feedback),将密文反馈给加密过程,可用于流加密。 |
OFB | 输出反馈模式(Output Feedback),类似于 CFB,但不会引入传输错误。 |
CTR | 计数器模式(Counter),将计数器值与密钥一起加密生成密文,可并行处理,适合高性能场景。 |
GCM | Galois/Counter 模式,提供认证的加密(AEAD),适合网络传输和安全通信。 |
3. 常见的填充方式
填充方式 | 描述 |
---|---|
PKCS5Padding | 常用于块加密,适用于块大小为 8 字节(如 DES)或 16 字节(如 AES)的加密算法。 |
PKCS7Padding | 类似于 PKCS5Padding,但适用于任意块大小。 |
NoPadding | 不进行填充,要求输入数据长度刚好是块大小的整数倍。 |
ISO10126Padding | 填充随机数据,最后一个字节表示填充字节数。 |
ZeroPadding | 用 0x00 填充,不推荐用于敏感数据(容易引发歧义)。 |
4. 示例组合
根据加密需求,可以选择不同的组合:
(1) AES/GCM/NoPadding
- 用途:认证加密(AEAD,Authenticated Encryption with Associated Data)。
- 特点:同时提供加密和数据完整性验证。
- 注意:使用 GCM 时通常不需要额外的填充方式。
(2) AES/CTR/NoPadding
- 用途:适合流加密或需要高并发的场景(如实时音视频传输)。
- 特点:将块加密转化为流加密,支持并行处理。
(3) AES/CFB/PKCS5Padding
- 用途:加密任意长度的数据。
- 特点:不需要填充数据块,但引入密文依赖。
(4) RSA/ECB/PKCS1Padding
- 用途:非对称加密,常用于密钥交换或数字签名。
- 特点:RSA 本质是块加密,ECB 模式足够安全(因为每块独立加密)。
5. 实际使用中的注意事项
-
选择加密模式:
- 如果数据长度较短且安全性要求高,优先使用 GCM。
- 如果需要流加密,使用 CTR 或 CFB。
- 避免使用 ECB,因为它容易被攻击。
-
填充选择:
- 推荐 PKCS5Padding 或 PKCS7Padding,它们是最常见的填充方式。
- 如果输入数据已经对齐块大小,可以使用 NoPadding。
-
随机性和安全性:
- 使用安全的随机数生成器(如
SecureRandom
)生成密钥和 IV。 - 确保密钥和 IV 不被硬编码或暴露。
- 使用安全的随机数生成器(如
-
兼容性考虑:
- 确保发送端和接收端使用相同的加密配置(算法、模式、填充方式等)。
下面举例:
1. AES/CBC/PKCS5Padding
用途:安全文件加密,推荐用于通用加密场景。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class AESCBCExample {
public static void main(String[] args) throws Exception {
// 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128); // AES-128
SecretKey secretKey = keyGen.generateKey();
// 生成初始化向量 (IV)
byte[] iv = new byte[16];
new java.security.SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// 原文
String plainText = "Hello, AES CBC Mode!";
// 加密
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes());
System.out.println("加密后的内容: " + javax.xml.bind.DatatypeConverter.printHexBinary(cipherText));
// 解密
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decryptedText = decryptCipher.doFinal(cipherText);
System.out.println("解密后的内容: " + new String(decryptedText));
}
}
2. AES/CTR/NoPadding
用途:适合实时音视频流加密,支持任意长度数据。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class AESCTRExample {
public static void main(String[] args) throws Exception {
// 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// 生成初始化向量 (IV)
byte[] iv = new byte[16];
new java.security.SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// 原文
String plainText = "Hello, AES CTR Mode!";
// 加密
Cipher encryptCipher = Cipher.getInstance("AES/CTR/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes());
System.out.println("加密后的内容: " + javax.xml.bind.DatatypeConverter.printHexBinary(cipherText));
// 解密
Cipher decryptCipher = Cipher.getInstance("AES/CTR/NoPadding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decryptedText = decryptCipher.doFinal(cipherText);
System.out.println("解密后的内容: " + new String(decryptedText));
}
}
3. AES/GCM/NoPadding
用途:适合网络通信,提供加密和数据完整性认证。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
public class AESGCMExample {
public static void main(String[] args) throws Exception {
// 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// 生成初始化向量 (IV)
byte[] iv = new byte[12]; // GCM 的 IV 通常为 12 字节
new java.security.SecureRandom().nextBytes(iv);
// 原文
String plainText = "Hello, AES GCM Mode!";
// 加密
Cipher encryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv); // 认证标签位数 128 位
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmSpec);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes());
System.out.println("加密后的内容: " + javax.xml.bind.DatatypeConverter.printHexBinary(cipherText));
// 解密
Cipher decryptCipher = Cipher.getInstance("AES/GCM/NoPadding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, gcmSpec);
byte[] decryptedText = decryptCipher.doFinal(cipherText);
System.out.println("解密后的内容: " + new String(decryptedText));
}
}
4. RSA/ECB/PKCS1Padding
用途:常用于加密小数据块(如密钥)或数字签名。
import javax.crypto.Cipher;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
public class RSAExample {
public static void main(String[] args) throws Exception {
// 生成 RSA 密钥对
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048); // 密钥长度 2048 位
KeyPair keyPair = keyGen.generateKeyPair();
// 原文
String plainText = "Hello, RSA ECB Mode!";
// 加密
Cipher encryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes());
System.out.println("加密后的内容: " + javax.xml.bind.DatatypeConverter.printHexBinary(cipherText));
// 解密
Cipher decryptCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
byte[] decryptedText = decryptCipher.doFinal(cipherText);
System.out.println("解密后的内容: " + new String(decryptedText));
}
}
5. AES/CFB/PKCS5Padding
用途:加密任意长度数据,适用于需要部分加密的流式场景。
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class AESCFBExample {
public static void main(String[] args) throws Exception {
// 生成密钥
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey secretKey = keyGen.generateKey();
// 初始化向量 (IV)
byte[] iv = new byte[16];
new java.security.SecureRandom().nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
// 原文
String plainText = "Hello, AES CFB Mode!";
// 加密
Cipher encryptCipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
byte[] cipherText = encryptCipher.doFinal(plainText.getBytes());
System.out.println("加密后的内容: " + javax.xml.bind.DatatypeConverter.printHexBinary(cipherText));
// 解密
Cipher decryptCipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decryptedText = decryptCipher.doFinal(cipherText);
System.out.println("解密后的内容: " + new String(decryptedText));
}
}