常用加密算法之 SM4 简介及应用

一、SM4 简介

SM4 是中国国家密码管理局提出的一种分组密码算法,也称为 SMS4。它属于对称加密算法,分组长度为 128 比特,密钥长度也为 128 比特。SM4 算法采用了与 AES 类似的轮函数结构,但具体的 S 盒和线性变换与 AES 不同,因此具有独特的加密性能。

1. 算法特点

分组长度:128 比特(16 字节)
密钥长度:128 比特(16 字节)
轮数:32 轮
安全强度:与 AES 相当,满足各种安全应用场景

2. 算法结构

SM4 算法主要由密钥扩展算法和轮函数(Round Function)组成。密钥扩展算法将 128 比特的密钥扩展成 32 个 32 比特的轮密钥。轮函数则通过非线性变换和线性变换对输入数据进行多轮迭代,最终输出加密结果。

3. 安全性

SM4 算法已经经过严格的数学分析和实际测试,证明了其具有较高的安全性。在同等密钥长度下,SM4 的安全性与 AES 相当,能够满足各种安全应用场景的需求。

4. SM4算法中5种基本模式的简介

1). ECB(电子密码本模式)

简介:ECB模式将数据分成块大小并独立加密每个块,相同的明文块会产生相同的密文块。
使用场景:由于安全性较低,通常不推荐使用ECB模式,除非在一些特殊场合,比如需要加密大量重复数据块。

2). CBC(密码块链接模式)–推荐

简介:CBC模式使用前一个块的密文与当前块的明文进行XOR操作后再加密,保证了即使相同的明文块也会产生不同的密文块。
使用场景:适用于需要较高安全性的场合,如文件加密、网络通信等。

3). CFB(密码反馈模式)

简介:CFB模式将加密算法当作流密码使用,将上一次加密的结果反馈到下一次加密过程中。
使用场景:适用于需要加密字节流或实时数据传输的场景。

4). OFB(输出反馈模式)

简介:OFB模式生成一个密钥流,然后将这个密钥流与明文进行XOR操作生成密文。与CFB类似,但密钥流的生成方式不同。
使用场景:适用于需要加密大量数据且对加密速度有一定要求的场景。

5). CTR(计数器模式)

简介:CTR模式将块加密算法变为流密码模式,使用一个递增的计数器与密钥一起加密一个固定值,然后将结果与明文进行XOR操作生成密文。
使用场景:适用于需要高安全性和高效率的加密场景,特别适合大数据量的加密。

二、Spring Boot集成SM4加密算法实战

1. 添加依赖

首先,需要在Spring Boot项目的 pom.xml 文件中添加Bouncy Castle库的依赖

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.68</version> <!-- 请使用最新版本 -->
</dependency>

2. 实现 SM4 帮助类

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;

public class SM4Util {

    private static final String ALGORITHM = "SM4/CBC/PKCS5Padding";
    private static final String KEY = "your-128-bit-key-here"; // 密钥,长度必须是16字节
    private static final String IV = "your-iv-here"; // 初始化向量,长度必须是16字节

    /**
     * 生成SM4密钥
     *
     * @return SecretKey 对象
     * @throws NoSuchAlgorithmException 如果找不到算法
     */
    public static SecretKey generateKey() throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("SM4");
        keyGenerator.init(128);
        return keyGenerator.generateKey();
    }

    /**
     * 加密数据
     *
     * @param data 待加密的原始数据
     * @return 加密后的数据
     * @throws Exception 加密过程中可能抛出的异常
     */
    public static String encrypt(String data) throws Exception {
        return encrypt(data, KEY, IV);
    }

    /**
     * 加密数据,允许自定义密钥和IV
     *
     * @param data    待加密的原始数据
     * @param key     加密密钥
     * @param iv      初始化向量
     * @return 加密后的数据
     * @throws Exception 加密过程中可能抛出的异常
     */
    public static String encrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
        SecureRandom random = new SecureRandom(key.getBytes());
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "SM4"), ivSpec);
        byte[] encryptedData = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * 解密数据
     *
     * @param encryptedData 已加密的数据
     * @return 解密后的原始数据
     * @throws Exception 解密过程中可能抛出的异常
     */
    public static String decrypt(String encryptedData) throws Exception {
        return decrypt(encryptedData, KEY, IV);
    }

    /**
     * 解密数据,允许自定义密钥和IV
     *
     * @param encryptedData 已加密的数据
     * @param key           加密密钥
     * @param iv            初始化向量
     * @return 解密后的原始数据
     * @throws Exception 解密过程中可能抛出的异常
     */
    public static String decrypt(String encryptedData, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance(ALGORITHM, "BC");
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key.getBytes(), "SM4"), ivSpec);
        byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decryptedData);
    }
}
  1. 使用帮助类
    以下是如何使用SM4Util帮助类的示例:
public class SM4Demo {
    public static void main(String[] args) {
        try {
            // 待加密的原始数据
            String originalData = "Hello, World!";
            // 加密数据
            String encryptedData = SM4Util.encrypt(originalData);
            System.out.println("Encrypted: " + encryptedData);
            // 解密数据
            String decryptedData = SM4Util.decrypt(encryptedData);
            System.out.println("Decrypted: " + decryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、使用 Hutool 方式集成 SM4

  1. 引入 Hutool 工具 pom 依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>
  1. 使用生成的随机密钥
String content = "test中文";

// 随机生成密钥
SymmetricCrypto sm4 = SmUtil.sm4();

String encryptHex = sm4.encryptHex(content);
String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
  1. 使用自定义密钥
String content = "test中文frfewrewrwerwer---------------------------------------------------";

// 生成自定义密钥
byte[] key = KeyUtil.generateKey(SM4.ALGORITHM_NAME, 128).getEncoded();

SM4 sm4 = SmUtil.sm4(key);

String encryptHex = sm4.encryptHex(content);
String decryptStr = sm4.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);

参考文献 :国密算法工具-SmUtil

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值