常见加密算法(des,rsa,sm2,sm3,sm4)附Java代码实现

目录

Des分组加密CBC模式

代码

AES算法CTR/CBC模式分组

典型用例

代码

RSA 工作 ECB模式

优点

缺点

代码

SM2

应用

代码

SM3

代码

SM4分组加密

代码

总结


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-128AES-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(离散对数)在计算上不可行。

应用

  1. 数字证书:国密 HTTPS 证书(如云服务、政府网站)。

  2. 区块链:中国的数字人民币(DCEP)采用 SM2 签名。

  3. 电子合同:企业电子签章(如法大大、e签宝)。

  4. 物联网安全:设备身份认证与数据加密。

特性SM2RSAECDSA
密钥长度256-bit2048-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 字节),固定输出。

  • 分块处理

  • 非常安全,不支持反向破解

     

应用场景

  1. 数字签名

    • 与 SM2 配合使用(如 SM2 签名前对消息哈希)。

  2. 消息认证码(MAC)

    • 通过 HMAC-SM3 验证数据完整性(如金融交易)。

  3. 区块链

    • 中国部分区块链平台(如 FISCO BCOS)使用 SM3 计算交易哈希。

  4. 密码衍生

    • 从口令生成密钥(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 轮非线性迭代。

应用场景

  1. 金融支付

    • 银行卡芯片(PBOC 3.0 标准)、移动支付(如银联云闪付)。

  2. 物联网安全

    • 设备通信加密(如智能电表、车载终端)。

  3. 电子政务

    • 政府文件加密、政务云数据保护。

  4. 区块链

    • 部分中国区块链平台(如长安链)使用 SM4 加密交易数据。

特性SM4AES-128
分组长度128-bit128-bit
密钥长度128-bit128/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金融支付(银联)、物联网设备加密
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值