Java 8 Spring Boot 国密 SM4 CBC 模式加解密完整实现 (含完整注释)

本文提供 Java 8 Spring Boot 环境下使用国密 SM4 算法实现 CBC 模式加解密的完整代码示例,并包含详细注释和使用教程。

实现步骤:

  1. pom.xml 文件中添加相关依赖
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version>
</dependency>
  1. 创建 SM4CBCUtil 工具类
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.BlockCipherPadding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;

public class SM4CBCUtil {

    /**
     * SM4 CBC 加密
     *
     * @param originData 原始数据
     * @param key        密钥
     * @param iv         向量
     * @return 加密后数据
     */
    public static byte[] encrypt(byte[] originData, byte[] key, byte[] iv) throws Exception {
        BlockCipher cipher = new CBCBlockCipher(new SM4Engine());
        BlockCipherPadding padding = new PKCS7Padding();
        BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(cipher);
        ParametersWithIV parametersWithIV = new ParametersWithIV(new KeyParameter(key), iv);
        bufferedBlockCipher.init(true, parametersWithIV);
        byte[] outBuf = new byte[bufferedBlockCipher.getOutputSize(originData.length)];
        int outOff = bufferedBlockCipher.processBytes(originData, 0, originData.length, outBuf, 0);
        outOff += bufferedBlockCipher.doFinal(outBuf, outOff);
        byte[] result = new byte[outOff];
        System.arraycopy(outBuf, 0, result, 0, outOff);
        return result;
    }

    /**
     * SM4 CBC 解密
     *
     * @param encryptData 加密后数据
     * @param key         密钥
     * @param iv          向量
     * @return 解密后数据
     */
    public static byte[] decrypt(byte[] encryptData, byte[] key, byte[] iv) throws Exception {
        BlockCipher cipher = new CBCBlockCipher(new SM4Engine());
        BlockCipherPadding padding = new PKCS7Padding();
        BufferedBlockCipher bufferedBlockCipher = new BufferedBlockCipher(cipher);
        ParametersWithIV parametersWithIV = new ParametersWithIV(new KeyParameter(key), iv);
        bufferedBlockCipher.init(false, parametersWithIV);
        byte[] outBuf = new byte[bufferedBlockCipher.getOutputSize(encryptData.length)];
        int outOff = bufferedBlockCipher.processBytes(encryptData, 0, encryptData.length, outBuf, 0);
        outOff += bufferedBlockCipher.doFinal(outBuf, outOff);
        byte[] result = new byte[outOff];
        System.arraycopy(outBuf, 0, result, 0, outOff);
        return result;
    }

    /**
     * 随机生成 16 字节向量
     *
     * @return 向量
     */
    public static byte[] generateIv() {
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        return iv;
    }

    /**
     * 字符串转换成 16 进制字符串
     *
     * @param str 待转换字符串
     * @return 16 进制字符串
     */
    public static String str2Hex(String str) {
        byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
        StringBuilder hex = new StringBuilder();
        for (byte b : bytes) {
            hex.append(String.format("%02x", b));
        }
        return hex.toString();
    }

    /**
     * 16 进制字符串转换成字符串
     *
     * @param hex 待转换 16 进制字符串
     * @return 字符串
     */
    public static String hex2Str(String hex) {
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16);
        }
        return new String(bytes, StandardCharsets.UTF_8);
    }

}
  1. 使用示例
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.util.Base64Utils;

@SpringBootApplication
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);

        // 原始数据
        String originData = 'Hello, world!';

        // 密钥(16 字节)
        String key = '1234567890abcdef';

        // 随机生成 16 字节向量
        byte[] iv = SM4CBCUtil.generateIv();

        // 加密
        byte[] encryptData = SM4CBCUtil.encrypt(originData.getBytes(), key.getBytes(), iv);

        // 将加密后数据转换成 Base64 字符串
        String encryptDataStr = Base64Utils.encodeToString(encryptData);

        // 输出加密后数据
        System.out.println('加密后数据:' + encryptDataStr);

        // 将 Base64 字符串转换成加密后数据
        byte[] encryptDataBytes = Base64Utils.decodeFromString(encryptDataStr);

        // 解密
        byte[] decryptData = SM4CBCUtil.decrypt(encryptDataBytes, key.getBytes(), iv);

        // 输出解密后数据
        System.out.println('解密后数据:' + new String(decryptData));
    }

}

加解密完整实现和注释都已完成,这里提供了一个 SpringBoot 项目的示例,完整代码可以在 Github 上查看:https://github.com/DerekYRC/SM4-CBC-SpringBoot-Demo

Java 8 Spring Boot 国密 SM4 CBC 模式加解密完整实现 (含完整注释)

原文地址: https://www.cveoy.top/t/topic/n0VV 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录