目录
Des分组加密CBC模式
特性 | 参数值/说明 |
---|---|
类型 | 对称分组加密 |
分组长度 | 64位(8字节) |
有效密钥长度 | 56位(+8位奇偶校验位,共64位) |
轮数 | 16轮Feistel结构 |
攻击类型 | 效果 | 所需资源 |
---|---|---|
暴力破解 | 56位密钥可在24小时内破解 | 云服务器集群(约$10,000成本) |
差分分析 | 理论攻击需2⁴⁷选择明文 | 学术研究可行,实际难实施 |
线性分析 | 理论攻击需2⁴³已知明文 | 同上 |
Sweet32攻击 | CBC模式下的碰撞攻击 | 2³²次加密操作 |
-
密钥过短:56位密钥空间仅2⁵⁶ ≈ 7.2×10¹⁶种可能
-
S盒设计:1970年代的设计可能隐藏后门(尽管未被证实)
-
分组限制:64位分组易受生日攻击
问题 导致结果 解决方案 固定S盒,是固定查表,缺乏数学约束 潜在代数攻击风险 AES使用可逆S盒 慢速密钥调度 侧信道攻击漏洞 AES的密钥扩展更复杂 无模式支持 需手动实现CBC等 AES原生支持GCM/CTR等模式
代码
package com.wwb.test20256200402.des;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.util.Base64;
/**
* DES对称加密,这里调用了算返库,没有从代码表面体现16轮的循环加密
*/
public class DESExample {
public static String encrypt(String data, String key) {
try {
// 检查密钥长度
if (key.length() != 8) {
throw new IllegalArgumentException("密钥必须是8个字符(64位)");
}
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] encryptedData = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static String decrypt(String encryptedData, String key) {
try {
if (key.length() != 8) {
throw new IllegalArgumentException("密钥必须是8个字符(64位)");
}
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decryptedData);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String originalData = "Hello wangwenbo";
String key = "12345678"; // 必须8字节
System.out.println("原始数据: " + originalData);
String encryptedData = encrypt(originalData, key);
System.out.println("加密后(Base64): " + encryptedData);
String decryptedData = decrypt(encryptedData, key);
System.out.println("解密后: " + decryptedData);
}
}
AES算法CTR/CBC模式分组
特性 | 参数值/说明 |
---|---|
类型 | 对称分组加密 |
分组长度 | 128位(16字节) |
密钥长度 | 128/192/256位(16/24/32字节) |
轮数 | 10轮(128位密钥) 12轮(192位) 14轮(256位) |
攻击类型 | AES-128 | AES-256 |
---|---|---|
暴力破解 | 2¹²⁸次操作 | 2²⁵⁶次操作 |
差分分析 | 需2¹²⁶明文 | 需2²⁵⁴明文 |
侧信道攻击 | 易受Cache计时攻击 | 需更复杂条件 |
特性 | DES(1977) | AES(2001) |
---|---|---|
密钥长度 | 56位 | 128/192/256位 |
分组大小 | 64位 | 128位 |
结构类型 | Feistel网络 | SPN结构 |
S盒设计 | 固定(黑盒) | 公开数学构造 |
安全寿命 | 已淘汰 | 预计安全至2030年+ |
典型用例
-
TLS 1.3:强制使用AES-GCM
-
磁盘加密:BitLocker(AES-XTS模式)
-
无线安全:Wi-Fi WPA2/3的CCMP协议
-
数据库加密:透明数据加密(TDE)
代码
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.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class AESUtil {
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding"; // 使用CBC模式和PKCS5填充
private static final int KEY_SIZE = 256; // AES-256
/**
* 生成AES密钥
*/
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(KEY_SIZE);
return keyGenerator.generateKey();
}
/**
* 生成初始化向量(IV)
*/
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16]; // AES块大小是16字节
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
/**
* AES加密
* @param plainText 明文
* @param key 密钥
* @param iv 初始化向量
* @return Base64编码的加密结果
*/
public static String encrypt(String plainText, SecretKey key, IvParameterSpec iv) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
/**
* AES解密
* @param encryptedText Base64编码的密文
* @param key 密钥
* @param iv 初始化向量
* @return 解密后的明文
*/
public static String decrypt(String encryptedText, SecretKey key, IvParameterSpec iv) throws Exception {
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
/**
* 将密钥转换为Base64字符串
*/
public static String keyToString(SecretKey key) {
return Base64.getEncoder().encodeToString(key.getEncoded());
}
/**
* 从Base64字符串恢复密钥
*/
public static SecretKey stringToKey(String keyStr) {
byte[] decodedKey = Base64.getDecoder().decode(keyStr);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
}
public static void main(String[] args) {
try {
// 1. 生成密钥和IV
SecretKey key = generateKey();
IvParameterSpec iv = generateIv();
// 2. 原始数据
String originalText = "这是一段需要加密的敏感数据";
System.out.println("原始文本: " + originalText);
// 3. 加密
String encryptedText = encrypt(originalText, key, iv);
System.out.println("加密后: " + encryptedText);
// 4. 解密
String decryptedText = decrypt(encryptedText, key, iv);
System.out.println("解密后: " + decryptedText);
// 5. 测试密钥序列化和反序列化
String keyStr = keyToString(key);
SecretKey restoredKey = stringToKey(keyStr);
System.out.println("使用序列化后的密钥解密: " +
decrypt(encryptedText, restoredKey, iv));
} catch (Exception e) {
e.printStackTrace();
}
}
}
RSA 工作 ECB模式
优点
数字签名、密钥交换、安全通信(如HTTPS)等领域 是目前最广泛使用的公钥算法之一
-
标准化:广泛支持(TLS、SSH、PGP)。
-
功能全面:支持加密、签名、密钥交换。
缺点
-
计算慢:比 ECC(如 SM2)慢 10-100 倍。
-
密钥长:2048-bit RSA ≈ 256-bit ECC 安全性。
代码
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAUtil {
private static final String ALGORITHM = "RSA";
private static final int KEY_SIZE = 2048; // RSA密钥长度,推荐至少2048位
/**
* 生成RSA密钥对
*/
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
return keyPairGenerator.generateKeyPair();
}
/**
* 公钥加密
* @param plainText 明文
* @param publicKey 公钥
* @return Base64编码的加密结果
*/
public static String encrypt(String plainText, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
/**
* 私钥解密
* @param encryptedText Base64编码的密文
* @param privateKey 私钥
* @return 解密后的明文
*/
public static String decrypt(String encryptedText, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);
byte[] decryptedBytes = cipher.doFinal(decodedBytes);
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
/**
* 使用私钥签名
* @param data 原始数据
* @param privateKey 私钥
* @return Base64编码的签名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
byte[] signBytes = signature.sign();
return Base64.getEncoder().encodeToString(signBytes);
}
/**
* 使用公钥验证签名
* @param data 原始数据
* @param sign Base64编码的签名
* @param publicKey 公钥
* @return 验证结果
*/
public static boolean verify(String data, String sign, PublicKey publicKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(data.getBytes(StandardCharsets.UTF_8));
return signature.verify(Base64.getDecoder().decode(sign));
}
/**
* 将公钥转换为Base64字符串
*/
public static String publicKeyToString(PublicKey publicKey) {
return Base64.getEncoder().encodeToString(publicKey.getEncoded());
}
/**
* 将私钥转换为Base64字符串
*/
public static String privateKeyToString(PrivateKey privateKey) {
return Base64.getEncoder().encodeToString(privateKey.getEncoded());
}
/**
* 从Base64字符串恢复公钥
*/
public static PublicKey stringToPublicKey(String publicKeyStr) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePublic(keySpec);
}
/**
* 从Base64字符串恢复私钥
*/
public static PrivateKey stringToPrivateKey(String privateKeyStr) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
return keyFactory.generatePrivate(keySpec);
}
public static void main(String[] args) {
try {
// 1. 生成密钥对
KeyPair keyPair = generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 2. 原始数据
String originalText = "这是一段需要RSA加密的敏感数据";
System.out.println("原始文本: " + originalText);
// 3. 加密解密测试
String encryptedText = encrypt(originalText, publicKey);
System.out.println("加密后: " + encryptedText);
String decryptedText = decrypt(encryptedText, privateKey);
System.out.println("解密后: " + decryptedText);
// 4. 签名验证测试
String signature = sign(originalText, privateKey);
System.out.println("签名: " + signature);
boolean isValid = verify(originalText, signature, publicKey);
System.out.println("签名验证结果: " + isValid);
// 5. 测试密钥序列化和反序列化
String publicKeyStr = publicKeyToString(publicKey);
String privateKeyStr = privateKeyToString(privateKey);
PublicKey restoredPublicKey = stringToPublicKey(publicKeyStr);
PrivateKey restoredPrivateKey = stringToPrivateKey(privateKeyStr);
System.out.println("使用序列化后的密钥解密: " +
decrypt(encryptedText, restoredPrivateKey));
} catch (Exception e) {
e.printStackTrace();
}
}
}
SM2
SM2 基于椭圆曲线离散对数问题(ECDLP),其安全性依赖于:
-
给定椭圆曲线上的点 GG 和整数 kk,计算 Q=kGQ=k**G(标量乘法)容易。
-
但已知 GG 和 QQ,求 kk(离散对数)在计算上不可行。
应用
-
数字证书:国密 HTTPS 证书(如云服务、政府网站)。
-
区块链:中国的数字人民币(DCEP)采用 SM2 签名。
-
电子合同:企业电子签章(如法大大、e签宝)。
-
物联网安全:设备身份认证与数据加密。
特性 | SM2 | RSA | ECDSA |
---|---|---|---|
密钥长度 | 256-bit | 2048-bit(同等安全) | 256-bit |
安全性 | 国密标准,抗侧信道攻击 | 依赖大数分解 | 国际通用 ECC |
计算速度 | 快(适合移动设备) | 慢 | 快 |
标准化 | 中国商用密码标准(GM/T) | 国际通用 | 国际通用 |
代码
package com.wwb.test20256200402.sm2;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import java.security.*;
import java.util.Base64;
/**
* 生成SM2密钥对,公钥加密,私钥解密
*/
public class SM2Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static KeyPair generateKeyPair() throws Exception {
// 获取SM2椭圆曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
ECParameterSpec ecParameterSpec = new ECParameterSpec(
sm2ECParameters.getCurve(),
sm2ECParameters.getG(),
sm2ECParameters.getN(),
sm2ECParameters.getH());
// 生成密钥对
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
keyPairGenerator.initialize(ecParameterSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
/**
* SM2加密
* @param publicKey 公钥
* @param data 待加密数据
* @return 加密后的Base64字符串
*/
public static String encrypt(PublicKey publicKey, byte[] data) throws Exception {
BCECPublicKey ecPublicKey = (BCECPublicKey) publicKey;
ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(
ecPublicKey.getQ(),
new ECDomainParameters(ecPublicKey.getParameters().getCurve(),
ecPublicKey.getParameters().getG(),
ecPublicKey.getParameters().getN()));
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));
byte[] encrypted = sm2Engine.processBlock(data, 0, data.length);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* SM2解密
* @param privateKey 私钥
* @param encryptedData Base64编码的加密数据
* @return 解密后的原始数据
*/
public static byte[] decrypt(PrivateKey privateKey, String encryptedData) throws Exception {
BCECPrivateKey ecPrivateKey = (BCECPrivateKey) privateKey;
ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(
ecPrivateKey.getD(),
new ECDomainParameters(ecPrivateKey.getParameters().getCurve(),
ecPrivateKey.getParameters().getG(),
ecPrivateKey.getParameters().getN()));
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, privateKeyParameters);
byte[] encrypted = Base64.getDecoder().decode(encryptedData);
return sm2Engine.processBlock(encrypted, 0, encrypted.length);
}
public static void main(String[] args) throws Exception {
// 1. 生成密钥对
KeyPair keyPair = generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
System.out.println("公钥: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
System.out.println("私钥: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
// 2. 加密测试
String originalText = "这是一段需要加密的敏感数据";
System.out.println("原始数据: " + originalText);
String encrypted = encrypt(publicKey, originalText.getBytes("UTF-8"));
System.out.println("加密结果(Base64): " + encrypted);
// 3. 解密测试
byte[] decrypted = decrypt(privateKey, encrypted);
System.out.println("解密结果: " + new String(decrypted, "UTF-8"));
}
}
SM3
-
哈希长度:256 位(32 字节),固定输出。
-
分块处理
-
非常安全,不支持反向破解
应用场景
-
数字签名:
-
与 SM2 配合使用(如 SM2 签名前对消息哈希)。
-
-
消息认证码(MAC):
-
通过 HMAC-SM3 验证数据完整性(如金融交易)。
-
-
区块链:
-
中国部分区块链平台(如 FISCO BCOS)使用 SM3 计算交易哈希。
-
-
密码衍生:
-
从口令生成密钥(PBKDF2-SM3)。
-
代码
package com.wwb.test20256200402.sm3;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import java.security.Security;
/**
* 固定输出256位(32字节,64个16进制字符)
*/
public class SM3Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* 计算SM3哈希值
* @param input 原始数据
* @return 64字符的16进制哈希字符串
*/
public static String hash(byte[] input) {
SM3Digest digest = new SM3Digest();
digest.update(input, 0, input.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
return Hex.toHexString(hash);
}
/**
* 计算SM3哈希值(重载String版本)
* @param input 原始字符串
* @return 64字符的16进制哈希字符串
*/
public static String hash(String input) {
return hash(input.getBytes());
}
public static void main(String[] args) {
// 示例1: 哈希字节数组
byte[] data1 = "Hello, SM3!".getBytes();
String hash1 = hash(data1);
System.out.println("哈希结果1: " + hash1);
// 示例2: 哈希字符串
String data2 = "这是一段需要哈希的中文";
String hash2 = hash(data2);
System.out.println("哈希结果2: " + hash2);
// 示例3: 空字符串哈希
String hash3 = hash("");
System.out.println("空字符串哈希: " + hash3);
// 示例4: 相同输入产生相同输出
String hash4 = hash("确定性测试");
String hash5 = hash("确定性测试");
System.out.println("相同输入哈希是否一致: " + hash4.equals(hash5));
}
}
SM4分组加密
-
分组长度:128 位(16 字节)。
-
密钥长度:128 位(16 字节)。
-
加密轮数:32 轮非线性迭代。
应用场景
-
金融支付:
-
银行卡芯片(PBOC 3.0 标准)、移动支付(如银联云闪付)。
-
-
物联网安全:
-
设备通信加密(如智能电表、车载终端)。
-
-
电子政务:
-
政府文件加密、政务云数据保护。
-
-
区块链:
-
部分中国区块链平台(如长安链)使用 SM4 加密交易数据。
-
特性 | SM4 | AES-128 |
---|---|---|
分组长度 | 128-bit | 128-bit |
密钥长度 | 128-bit | 128/192/256-bit |
加密轮数 | 32 轮 | 10/12/14 轮 |
设计结构 | Feistel 网络 | SPN 网络(Substitution-Permutation) |
性能 | 软件实现略慢,硬件优化后接近 AES | 硬件加速(AES-NI)极快 |
标准化 | 中国国密(GM/T) | 国际通用(NIST) |
代码
package com.wwb.test20256200402.sm4;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import java.util.Base64;
public class SM4Example {
static {
Security.addProvider(new BouncyCastleProvider());
}
// 加密算法名称
private static final String ALGORITHM_NAME = "SM4";
// 默认分组模式与填充方式
private static final String DEFAULT_CIPHER_ALGORITHM = "SM4/CBC/PKCS5Padding";
// 默认初始化向量(IV)长度
private static final int IV_LENGTH = 16; // 128 bits
/**
* 生成SM4密钥
* @return 16字节(128位)的SM4密钥
*/
public static byte[] generateKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, "BC");
kg.init(128); // SM4固定使用128位密钥
SecretKey secretKey = kg.generateKey();
return secretKey.getEncoded();
}
/**
* 生成随机初始化向量(IV)
*/
public static byte[] generateIV() {
byte[] iv = new byte[IV_LENGTH];
new java.security.SecureRandom().nextBytes(iv);
return iv;
}
/**
* SM4加密
* @param key 16字节的SM4密钥
* @param iv 16字节的初始化向量(ECB模式可传null)
* @param plaintext 明文数据
* @return 加密后的Base64字符串
*/
public static String encrypt(byte[] key, byte[] iv, byte[] plaintext) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM, "BC");
if (iv != null) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
}
byte[] encrypted = cipher.doFinal(plaintext);
return Base64.getEncoder().encodeToString(encrypted);
}
/**
* SM4解密
* @param key 16字节的SM4密钥
* @param iv 16字节的初始化向量(ECB模式可传null)
* @param ciphertext Base64编码的密文
* @return 解密后的原始数据
*/
public static byte[] decrypt(byte[] key, byte[] iv, String ciphertext) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM_NAME);
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM, "BC");
if (iv != null) {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
} else {
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
}
byte[] encryptedData = Base64.getDecoder().decode(ciphertext);
return cipher.doFinal(encryptedData);
}
public static void main(String[] args) throws Exception {
// 1. 生成密钥和IV
byte[] key = generateKey();
byte[] iv = generateIV();
System.out.println("SM4密钥(Base64): " + Base64.getEncoder().encodeToString(key));
System.out.println("初始化向量(Base64): " + Base64.getEncoder().encodeToString(iv));
// 2. 加密测试
String originalText = "这是一段需要加密的敏感数据";
System.out.println("\n原始文本: " + originalText);
String encryptedText = encrypt(key, iv, originalText.getBytes("UTF-8"));
System.out.println("加密结果(Base64): " + encryptedText);
// 3. 解密测试
byte[] decryptedBytes = decrypt(key, iv, encryptedText);
String decryptedText = new String(decryptedBytes, "UTF-8");
System.out.println("解密结果: " + decryptedText);
// 4. 验证解密是否正确
System.out.println("解密是否成功: " + originalText.equals(decryptedText));
}
}
总结
算法 | 类型 | 密钥/输出长度 | 安全性状态 | 不安全原因(若存在) | 典型应用场景 |
---|---|---|---|---|---|
DES | 对称分组加密 | 56-bit(有效密钥) | 已淘汰 | 1. 密钥过短(暴力破解24小时内) 2. 64位分组易受碰撞攻击 3. S盒设计老旧 | 传统遗留系统(如老旧POS机) |
3DES | 对称分组加密 | 168-bit(三密钥) | 逐步淘汰 | 1. 计算速度慢 2. 仍存在理论侧信道攻击 | 银行芯片卡(逐步替换为AES/SM4) |
AES | 对称分组加密 | 128/192/256-bit | 安全(至2030+) | 1. 侧信道攻击(需硬件防护) 2. 量子计算威胁(Grover算法) | TLS 1.3、磁盘加密(BitLocker)、物联网 |
RSA | 非对称加密 | 2048-bit(推荐) | 安全但效率低 | 1. 计算慢(比ECC慢10-100倍) 2. 量子Shor算法威胁 | HTTPS证书、SSH密钥交换、数字签名 |
SM2 | 非对称加密(ECC) | 256-bit | 安全(国密标准) | 1. 需国产化支持 2. 国际兼容性较低 | 数字人民币(DCEP)、电子政务、国密HTTPS |
SM3 | 密码哈希 | 256-bit(固定输出) | 安全(国密标准) | 1. 无公开漏洞 2. 国际普及度低 | 数字签名(配合SM2)、区块链哈希 |
SM4 | 对称分组加密 | 128-bit | 安全(国密标准) | 1. 软件实现效率略低于AES | 金融支付(银联)、物联网设备加密 |