SM4加密算法

SM4加密算法

复制代码
/**
 * SM4加密工具类
 * SM4算法是一种分组密码算法,分组长度为128位,密钥长度为128位
 */
public class SM4Util {

    static {
        // 加入BouncyCastle支持
        Security.addProvider(new BouncyCastleProvider());
    }

    // 算法名称
    public static final String ALGORITHM_NAME = "SM4";
    // 加密算法/分组加密模式/填充方式
    public static final String ALGORITHM_NAME_ECB_PADDING = "SM4/ECB/PKCS5Padding";
    public static final String ALGORITHM_NAME_CBC_PADDING = "SM4/CBC/PKCS5Padding";
    // 密钥长度,128位
    public static final int KEY_SIZE = 128;

    /**
     * 生成ECB模式的密钥
     * @return 16位密钥
     * @throws Exception 异常
     */
    public static String generateKey() throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM_NAME, BouncyCastleProvider.PROVIDER_NAME);
        kg.init(KEY_SIZE, new SecureRandom());
        return ByteUtils.toHexString(kg.generateKey().getEncoded());
    }

    /**
     * 生成CBC模式的初始化向量
     * @return 16位初始化向量
     */
    public static String generateIV() {
        SecureRandom random = new SecureRandom();
        byte[] iv = new byte[16];
        random.nextBytes(iv);
        return ByteUtils.toHexString(iv);
    }

    /**
     * ECB模式加密
     * @param plainText 明文
     * @param key 密钥(16位十六进制字符串)
     * @return 加密后的Base64字符串
     * @throws Exception 异常
     */
    public static String encryptEcb(String plainText, String key) throws Exception {
        // 将密钥转换为字节数组
        byte[] keyData = ByteUtils.fromHexString(key);
        // 初始化密钥
        Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);

        // 实例化加密器
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        // 加密
        byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        // 返回Base64编码结果
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * ECB模式解密
     * @param cipherText 加密后的Base64字符串
     * @param key 密钥(16位十六进制字符串)
     * @return 解密后的明文
     * @throws Exception 异常
     */
    public static String decryptEcb(String cipherText, String key) throws Exception {
        // 解码Base64
        byte[] encryptedData = Base64.getDecoder().decode(cipherText);
        // 将密钥转换为字节数组
        byte[] keyData = ByteUtils.fromHexString(key);
        // 初始化密钥
        Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);

        // 实例化解密器
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_ECB_PADDING, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);

        // 解密
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }

    /**
     * CBC模式加密
     * @param plainText 明文
     * @param key 密钥(16位十六进制字符串)
     * @param iv 初始化向量(16位十六进制字符串)
     * @return 加密后的Base64字符串
     * @throws Exception 异常
     */
    public static String encryptCbc(String plainText, String key, String iv) throws Exception {
        // 将密钥和IV转换为字节数组
        byte[] keyData = ByteUtils.fromHexString(key);
        byte[] ivData = ByteUtils.fromHexString(iv);

        // 初始化密钥和IV
        Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);

        // 实例化加密器
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);

        // 加密
        byte[] encryptedData = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * CBC模式解密
     * @param cipherText 加密后的Base64字符串
     * @param key 密钥(16位十六进制字符串)
     * @param iv 初始化向量(16位十六进制字符串)
     * @return 解密后的明文
     * @throws Exception 异常
     */
    public static String decryptCbc(String cipherText, String key, String iv) throws Exception {
        // 解码Base64
        byte[] encryptedData = Base64.getDecoder().decode(cipherText);
        // 将密钥和IV转换为字节数组
        byte[] keyData = ByteUtils.fromHexString(key);
        byte[] ivData = ByteUtils.fromHexString(iv);

        // 初始化密钥和IV
        Key secretKey = new SecretKeySpec(keyData, ALGORITHM_NAME);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivData);

        // 实例化解密器
        Cipher cipher = Cipher.getInstance(ALGORITHM_NAME_CBC_PADDING, BouncyCastleProvider.PROVIDER_NAME);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);

        // 解密
        byte[] decryptedData = cipher.doFinal(encryptedData);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }
}
相关推荐
leaves falling2 分钟前
C/C++ const:修饰变量和指针的区别(和引用底层关系)
c语言·开发语言·c++
花千树-0103 分钟前
多步骤 ReAct 实战:让 Agent 自主完成航司比价与订票
java·agent·function call·react agent·harness·j-langchain·多步骤推理
xcLeigh12 分钟前
飞算 JavaAI 进阶实战:从代码生成到系统架构优化的全流程指南
java·系统架构·代码生成·java开发·飞算javaai炫技赛·javaai·飞算
比昨天多敲两行13 分钟前
C++11新特性
开发语言·c++
xiaoye-duck26 分钟前
【C++:C++11】核心特性实战:详解C++11列表初始化、右值引用与移动语义
开发语言·c++·c++11
希望永不加班41 分钟前
SpringBoot 事件机制:ApplicationEvent 与监听器
java·开发语言·spring boot·后端·spring
Nyarlathotep01131 小时前
自动内存管理(2):垃圾收集器与内存分配策略
java·jvm·后端
14年ABAP码农1 小时前
ABAP - call API with x-www-form-urlencoded
开发语言
却话巴山夜雨时i1 小时前
互联网大厂Java面试实录:技术栈解析与场景剖析
java·大数据·spring boot·spring cloud·微服务·ai·面试
好家伙VCC1 小时前
# 发散创新:基于事件驱动架构的实时日志监控系统设计与实现在现代分布式系统中,**事件驱动编程模型**正
java·python·架构