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);
    }
}
相关推荐
草履虫建模11 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq13 小时前
分布式系统安全通信
开发语言·c++·算法
qq_2975746713 小时前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
老毛肚13 小时前
MyBatis插件原理及Spring集成
java·spring·mybatis
学嵌入式的小杨同学13 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
lang2015092813 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
Re.不晚14 小时前
Java入门17——异常
java·开发语言
缘空如是14 小时前
基础工具包之JSON 工厂类
java·json·json切换
精彩极了吧14 小时前
C语言基本语法-自定义类型:结构体&联合体&枚举
c语言·开发语言·枚举·结构体·内存对齐·位段·联合
追逐梦想的张小年14 小时前
JUC编程04
java·idea