概述
对称加密算法使用相同的密钥进行加密和解密操作。这类算法速度快、效率高,适合加密大量数据。
目录
- AES (Advanced Encryption Standard)
- DES (Data Encryption Standard)
- 3DES (Triple DES)
- Blowfish
- Twofish
- ChaCha20
- SM4 (国密算法)
- 加密模式
- 性能对比
AES (Advanced Encryption Standard)
原理
AES是一种分组密码算法,使用128位固定块大小,密钥长度可以是128、192或256位。它基于Substitution-Permutation Network (SPN)结构。
核心操作:
- SubBytes: 使用S-box进行字节替换
- ShiftRows: 行移位操作
- MixColumns: 列混合操作(最后一轮除外)
- AddRoundKey: 与轮密钥异或
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 128位 (16字节) |
| 密钥长度 | 128/192/256位 |
| 轮数 | 10/12/14轮 (对应密钥长度) |
| 安全级别 | 非常高 |
| 状态 | NIST标准,广泛使用 |
应用场景
- 数据存储加密:文件系统、数据库字段加密
- 网络传输:TLS/SSL协议中的对称加密部分
- 磁盘加密:BitLocker、FileVault等
- 无线通信:WPA2/WPA3
- VPN:IPSec、OpenVPN
性能影响
- 加密/解密速度:非常快(现代CPU通常有硬件加速)
- 内存占用:低(约128字节状态)
- CPU使用率:低(硬件加速时几乎无影响)
- 吞吐量:可达到GB/s级别(取决于实现和硬件)
Java实现示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
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 AESExample {
/**
* AES-256-GCM加密示例(推荐模式)
* GCM提供加密和认证,防止篡改
*/
public static String encryptGCM(String plaintext, SecretKey key) throws Exception {
// 生成随机IV (12字节用于GCM)
byte[] iv = new byte[12];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
// 创建GCM参数(标签长度128位)
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
// 初始化加密器
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
// 执行加密
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// 将IV和密文组合(IV长度12字节)
byte[] encrypted = new byte[12 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 12);
System.arraycopy(ciphertext, 0, encrypted, 12, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* AES-256-GCM解密示例
*/
public static String decryptGCM(String encryptedData, SecretKey key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
// 提取IV和密文
byte[] iv = new byte[12];
System.arraycopy(encrypted, 0, iv, 0, 12);
byte[] ciphertext = new byte[encrypted.length - 12];
System.arraycopy(encrypted, 12, ciphertext, 0, ciphertext.length);
// 创建GCM参数
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
// 初始化解密器
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec);
// 执行解密
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
/**
* AES-CBC加密示例(兼容模式)
*/
public static String encryptCBC(String plaintext, SecretKey key) throws Exception {
// 生成随机IV (16字节用于CBC)
byte[] iv = new byte[16];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
// 初始化加密器(使用PKCS5Padding)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
// 执行加密
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// 将IV和密文组合
byte[] encrypted = new byte[16 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 16);
System.arraycopy(ciphertext, 0, encrypted, 16, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* AES-CBC解密示例
*/
public static String decryptCBC(String encryptedData, SecretKey key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
// 提取IV和密文
byte[] iv = new byte[16];
System.arraycopy(encrypted, 0, iv, 0, 16);
byte[] ciphertext = new byte[encrypted.length - 16];
System.arraycopy(encrypted, 16, ciphertext, 0, ciphertext.length);
// 初始化解密器
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
// 执行解密
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
/**
* 生成AES密钥
*/
public static SecretKey generateKey(int keySize) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keySize); // 128, 192, 或 256
return keyGenerator.generateKey();
}
/**
* 从字节数组创建密钥
*/
public static SecretKey createKeyFromBytes(byte[] keyBytes) {
return new SecretKeySpec(keyBytes, "AES");
}
/**
* 完整使用示例
*/
public static void main(String[] args) throws Exception {
// 生成256位密钥
SecretKey key = generateKey(256);
String originalText = "这是要加密的敏感数据";
// 使用GCM模式(推荐)
System.out.println("=== AES-GCM模式 ===");
String encryptedGCM = encryptGCM(originalText, key);
System.out.println("加密后: " + encryptedGCM);
String decryptedGCM = decryptGCM(encryptedGCM, key);
System.out.println("解密后: " + decryptedGCM);
// 使用CBC模式
System.out.println("\n=== AES-CBC模式 ===");
String encryptedCBC = encryptCBC(originalText, key);
System.out.println("加密后: " + encryptedCBC);
String decryptedCBC = decryptCBC(encryptedCBC, key);
System.out.println("解密后: " + decryptedCBC);
}
}
安全建议
✅ 推荐:
- 使用AES-256-GCM进行新项目开发
- 使用随机IV,每次加密都不同
- 安全存储密钥
❌ 避免:
- 使用ECB模式(不安全)
- 重复使用相同的IV
- 使用弱密钥(建议使用KeyGenerator)
DES (Data Encryption Standard)
原理
DES使用56位密钥(加上8位奇偶校验位)和64位块大小,基于Feistel网络结构。现已不安全,不应在新项目中使用。
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 64位 (8字节) |
| 密钥长度 | 56位 (实际64位,8位校验) |
| 轮数 | 16轮 |
| 安全级别 | 已不安全 ⚠️ |
| 状态 | 已废弃,不应使用 |
应用场景
❌ 已不建议使用,仅用于:
- 学习目的
- 兼容遗留系统(需要迁移)
性能影响
- 加密/解密速度:中等(硬件支持但已过时)
- 内存占用:低
- CPU使用率:中等
- 吞吐量:远低于AES
Java实现示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class DESExample {
/**
* DES加密示例(仅用于演示,不建议使用)
*/
public static String encrypt(String plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[8]; // DES使用8字节IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = new byte[8 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 8);
System.arraycopy(ciphertext, 0, encrypted, 8, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
return keyGenerator.generateKey();
}
public static void main(String[] args) throws Exception {
System.out.println("⚠️ 警告: DES已不安全,仅用于演示");
SecretKey key = generateKey();
String encrypted = encrypt("测试数据", key);
System.out.println("加密结果: " + encrypted);
}
}
安全建议
⚠️ 强烈建议:
- 不要在新项目中使用DES
- 迁移到AES-256
- 如需兼容,考虑3DES作为临时方案
3DES (Triple DES)
原理
3DES是对DES的增强,通过三次DES加密来提高安全性。使用2个或3个56位密钥。
加密模式:
- EEE: E(K₁, E(K₂, E(K₁, P)))
- EDE: E(K₁, D(K₂, E(K₁, P))) - 最常用
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 64位 (8字节) |
| 有效密钥长度 | 112位 (2-key) 或 168位 (3-key) |
| 安全级别 | 中等(已逐渐淘汰) |
| 状态 | 遗留系统使用,新项目不推荐 |
应用场景
- 遗留系统兼容:需要与旧系统交互
- 金融系统迁移期:从DES迁移到AES的过渡方案
- 嵌入式系统:资源受限但需要中等安全性
性能影响
- 加密/解密速度:慢(3倍DES操作)
- 内存占用:低
- CPU使用率:高(比AES慢3倍以上)
- 吞吐量:远低于AES
Java实现示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class TripleDESExample {
/**
* 3DES加密示例
*/
public static String encrypt(String plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[8]; // 3DES使用8字节IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = new byte[8 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 8);
System.arraycopy(ciphertext, 0, encrypted, 8, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* 3DES解密示例
*/
public static String decrypt(String encryptedData, SecretKey key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
byte[] iv = new byte[8];
System.arraycopy(encrypted, 0, iv, 0, 8);
byte[] ciphertext = new byte[encrypted.length - 8];
System.arraycopy(encrypted, 8, ciphertext, 0, ciphertext.length);
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
keyGenerator.init(168); // 168位密钥(3-key 3DES)
return keyGenerator.generateKey();
}
public static void main(String[] args) throws Exception {
System.out.println("⚠️ 注意: 3DES性能较差,建议迁移到AES");
SecretKey key = generateKey();
String original = "测试数据";
String encrypted = encrypt(original, key);
System.out.println("加密后: " + encrypted);
String decrypted = decrypt(encrypted, key);
System.out.println("解密后: " + decrypted);
}
}
安全建议
⚠️ 建议:
- 仅在需要兼容遗留系统时使用
- 优先考虑迁移到AES
- 使用168位密钥(3-key模式)
Blowfish
原理
Blowfish是由Bruce Schneier设计的对称分组密码算法,使用可变长度密钥(32-448位)和64位块大小。基于Feistel网络。
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 64位 (8字节) |
| 密钥长度 | 32-448位(通常128或256位) |
| 轮数 | 16轮 |
| 安全级别 | 中等(块大小较小) |
| 状态 | 仍在使用但不如AES流行 |
应用场景
- 文件加密工具:某些加密软件
- 数据库加密:部分数据库系统
- 游戏和娱乐软件:DRM系统
性能影响
- 加密/解密速度:快(无专利,实现简单)
- 内存占用:中等(需要S-box)
- CPU使用率:中等
- 吞吐量:高于DES但低于AES
Java实现示例
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class BlowfishExample {
public static String encrypt(String plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[8]; // Blowfish使用8字节IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = new byte[8 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 8);
System.arraycopy(ciphertext, 0, encrypted, 8, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String encryptedData, SecretKey key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
byte[] iv = new byte[8];
System.arraycopy(encrypted, 0, iv, 0, 8);
byte[] ciphertext = new byte[encrypted.length - 8];
System.arraycopy(encrypted, 8, ciphertext, 0, ciphertext.length);
Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
public static SecretKey generateKey(int keySize) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
keyGenerator.init(keySize); // 32-448位
return keyGenerator.generateKey();
}
public static void main(String[] args) throws Exception {
SecretKey key = generateKey(128);
String original = "测试数据";
String encrypted = encrypt(original, key);
System.out.println("加密后: " + encrypted);
String decrypted = decrypt(encrypted, key);
System.out.println("解密后: " + decrypted);
}
}
安全建议
⚠️ 注意:
- 块大小较小(64位),不适合加密大文件
- 建议使用256位密钥
- 新项目优先考虑AES
Twofish
原理
Twofish是AES竞赛的决赛算法之一,使用128位块大小和128、192或256位密钥。虽然没有被选为AES标准,但安全性很高。
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 128位 (16字节) |
| 密钥长度 | 128/192/256位 |
| 轮数 | 16轮 |
| 安全级别 | 高(与AES相当) |
| 状态 | 无专利,开源使用 |
应用场景
- TrueCrypt/VeraCrypt:磁盘加密工具
- PGP加密:某些版本的PGP
- 需要无专利算法的场景
性能影响
- 加密/解密速度:快(软件实现,无硬件加速)
- 内存占用:中等
- CPU使用率:中等
- 吞吐量:接近AES(软件实现时)
Java实现示例
// 注意:Java标准库不包含Twofish
// 需要使用BouncyCastle等第三方库
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.security.SecureRandom;
import java.util.Base64;
public class TwofishExample {
static {
// 添加BouncyCastle提供者
Security.addProvider(new BouncyCastleProvider());
}
public static String encrypt(String plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[16]; // Twofish使用16字节IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("Twofish/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = new byte[16 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 16);
System.arraycopy(ciphertext, 0, encrypted, 16, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
public static SecretKey generateKey(int keySize) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("Twofish", "BC");
keyGenerator.init(keySize);
return keyGenerator.generateKey();
}
public static void main(String[] args) throws Exception {
SecretKey key = generateKey(256);
String original = "测试数据";
String encrypted = encrypt(original, key);
System.out.println("加密后: " + encrypted);
}
}
安全建议
✅ 适合场景:
- 需要无专利算法
- 磁盘加密等特定应用
- 新项目建议使用AES(更广泛支持)
ChaCha20
原理
ChaCha20是Daniel J. Bernstein设计的流密码算法,使用256位密钥和96位nonce。它是Salsa20的改进版本,适合软件实现。
技术规格
| 属性 | 值 |
|---|---|
| 密钥长度 | 256位 |
| Nonce长度 | 96位 (12字节) |
| 块大小 | 512位 (流密码) |
| 轮数 | 20轮 |
| 安全级别 | 高 |
| 状态 | IETF标准,广泛使用 |
应用场景
- TLS/SSL:Google Chrome等浏览器的TLS实现
- VPN:WireGuard协议使用ChaCha20-Poly1305
- 移动设备:无硬件AES加速时性能更好
- 实时通信:低延迟要求
性能影响
- 加密/解密速度:非常快(软件实现时)
- 内存占用:低
- CPU使用率:低(纯软件实现高效)
- 吞吐量:在无硬件加速时优于AES
Java实现示例
import javax.crypto.Cipher;
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 ChaCha20Example {
/**
* ChaCha20加密(需要Java 11+)
*/
public static String encrypt(String plaintext, SecretKeySpec key) throws Exception {
// 生成随机nonce (12字节)
byte[] nonce = new byte[12];
SecureRandom random = new SecureRandom();
random.nextBytes(nonce);
// 创建ChaCha20参数(使用12字节nonce)
IvParameterSpec ivSpec = new IvParameterSpec(nonce);
// 初始化加密器
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
// 执行加密(Poly1305自动提供认证)
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
// 将nonce和密文组合
byte[] encrypted = new byte[12 + ciphertext.length];
System.arraycopy(nonce, 0, encrypted, 0, 12);
System.arraycopy(ciphertext, 0, encrypted, 12, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* ChaCha20解密
*/
public static String decrypt(String encryptedData, SecretKeySpec key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
// 提取nonce和密文
byte[] nonce = new byte[12];
System.arraycopy(encrypted, 0, nonce, 0, 12);
byte[] ciphertext = new byte[encrypted.length - 12];
System.arraycopy(encrypted, 12, ciphertext, 0, ciphertext.length);
IvParameterSpec ivSpec = new IvParameterSpec(nonce);
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
/**
* 从字节数组创建密钥
*/
public static SecretKeySpec createKey(byte[] keyBytes) {
return new SecretKeySpec(keyBytes, "ChaCha20");
}
public static void main(String[] args) throws Exception {
// 生成256位密钥
byte[] keyBytes = new byte[32];
SecureRandom random = new SecureRandom();
random.nextBytes(keyBytes);
SecretKeySpec key = createKey(keyBytes);
String original = "这是要加密的数据";
String encrypted = encrypt(original, key);
System.out.println("加密后: " + encrypted);
String decrypted = decrypt(encrypted, key);
System.out.println("解密后: " + decrypted);
}
}
安全建议
✅ 推荐:
- 移动设备或无AES硬件加速场景
- 需要低延迟的应用
- 与Poly1305结合使用(ChaCha20-Poly1305)
SM4 (国密算法)
原理
SM4是中国国家密码管理局发布的商用密码算法,使用128位密钥和128位块大小,基于Feistel网络结构。
技术规格
| 属性 | 值 |
|---|---|
| 块大小 | 128位 (16字节) |
| 密钥长度 | 128位 |
| 轮数 | 32轮 |
| 安全级别 | 高(国密标准) |
| 状态 | 中国标准,国内广泛使用 |
应用场景
- 政府系统:符合国家密码管理要求
- 金融行业:国内银行、支付系统
- 国产化替代:信创项目
- 密码合规:需要符合国密标准
性能影响
- 加密/解密速度:快(与AES相当)
- 内存占用:低
- CPU使用率:中等
- 吞吐量:与AES-128相当
Java实现示例
// 需要国密算法库支持,如BouncyCastle的国密扩展
// 或使用国产密码库
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.security.SecureRandom;
import java.util.Base64;
public class SM4Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* SM4加密(CBC模式)
*/
public static String encrypt(String plaintext, SecretKey key) throws Exception {
byte[] iv = new byte[16]; // SM4使用16字节IV
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = new byte[16 + ciphertext.length];
System.arraycopy(iv, 0, encrypted, 0, 16);
System.arraycopy(ciphertext, 0, encrypted, 16, ciphertext.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* SM4解密
*/
public static String decrypt(String encryptedData, SecretKey key) throws Exception {
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
byte[] iv = new byte[16];
System.arraycopy(encrypted, 0, iv, 0, 16);
byte[] ciphertext = new byte[encrypted.length - 16];
System.arraycopy(encrypted, 16, ciphertext, 0, ciphertext.length);
Cipher cipher = Cipher.getInstance("SM4/CBC/PKCS5Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
byte[] plaintext = cipher.doFinal(ciphertext);
return new String(plaintext, StandardCharsets.UTF_8);
}
public static SecretKey generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4", "BC");
return keyGenerator.generateKey();
}
public static void main(String[] args) throws Exception {
SecretKey key = generateKey();
String original = "测试数据";
String encrypted = encrypt(original, key);
System.out.println("加密后: " + encrypted);
String decrypted = decrypt(encrypted, key);
System.out.println("解密后: " + decrypted);
}
}
安全建议
✅ 适用场景:
- 需要符合国密标准
- 政府、金融等敏感行业
- 国产化项目
⚠️ 注意:
- 需要专门的国密算法库支持
- 国际兼容性较差
加密模式
CBC (Cipher Block Chaining)
原理: 每个明文块与前一个密文块异或后再加密。
特点:
- 需要IV(初始化向量)
- 串行处理,无法并行
- 填充攻击风险
Java示例:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
GCM (Galois/Counter Mode)
原理: CTR模式的变体,同时提供加密和认证。
特点:
- 认证加密(AEAD)
- 可以并行加密
- 防止篡改
Java示例:
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
CTR (Counter Mode)
原理: 使用计数器生成密钥流,与明文异或。
特点:
- 流密码模式
- 可并行
- 需要nonce
Java示例:
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
ECB (Electronic Codebook)
原理: 直接加密每个块,不依赖其他块。
特点:
- ⚠️ 不安全,不推荐使用
- 相同明文产生相同密文
- 无IV需求
性能对比
算法性能对比表
| 算法 | 密钥长度 | 速度(软件) | 硬件加速 | 推荐度 |
|---|---|---|---|---|
| AES-256 | 256位 | 快 | 广泛支持 | ⭐⭐⭐⭐⭐ |
| ChaCha20 | 256位 | 非常快 | 无 | ⭐⭐⭐⭐⭐ |
| AES-128 | 128位 | 快 | 广泛支持 | ⭐⭐⭐⭐ |
| SM4 | 128位 | 快 | 有限 | ⭐⭐⭐⭐ |
| Blowfish | 128-448位 | 中等 | 无 | ⭐⭐⭐ |
| 3DES | 168位 | 慢 | 有限 | ⭐⭐ |
| DES | 56位 | 中等 | 有限 | ❌ |
性能优化建议
- 使用硬件加速:AES在支持AES-NI的CPU上性能大幅提升
- 选择合适的模式:GCM模式可并行,性能更好
- 避免ECB模式:安全性差且性能无优势
- 密钥管理:密钥生成和存储不影响加密性能,但影响安全性
总结
推荐选择
现代应用:
- 首选:AES-256-GCM(通用场景)
- 备选:ChaCha20-Poly1305(移动/无硬件加速)
特殊需求:
- 国密合规:SM4
- 遗留系统:3DES(过渡方案)
不推荐:
- ❌ DES(已不安全)
- ❌ ECB模式(不安全)
- ❌ 弱密钥长度(<128位)
选择决策树
需要加密?
├─ 需要国密合规?→ SM4
├─ 有硬件AES加速?→ AES-256-GCM
├─ 无硬件加速/移动设备?→ ChaCha20-Poly1305
└─ 遗留系统兼容?→ 3DES(尽快迁移)