Spring HTTP请求与应答国密算法加解密(对称加密方式SM4)

本文介绍了如何在Spring中利用SM4算法实现HTTP请求与响应的加解密,包括使用Hutool库封装SM4算法、解决请求流只能读取一次的问题、创建加解密注解及处理类,并提供了具体的使用方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SM4算法成为行业标准:

  • SM4分组密码算法是2012年3月21日实施的一项行业标准;
  • 2021年6月25日,我国SM4分组密码算法作为国际标准ISO/IEC 18033-3:2010/AMD1:2021《信息技术 安全技术 加密算法 第3部分:分组密码 补篇1:SM4》,由国际标准化组织ISO/IEC正式发布;
  • 中文名SM4分组密码算法标准号GM/T 0002-2012实施日期2012-03-21发布日期2012-03-21技术归口国家密码管理局批准发布部门国家密码管理局。

SM4算法的重要性

是我国提出的分组密码算法,而且得到了国际的认可;是继SM2/SM9数字签名算法、SM3密码杂凑算法、祖冲之密码算法和SM9标识加密算法之后,我国又一个商用密码算法被纳入ISO/IEC国际标准正式发布;标志着我国商用密码算法国际标准体系进一步完善,展现了我国先进的密码科技水平和国际标准化能力,对提升我国商用密码产业发展、推动商用密码更好服务“一带一路”建设具有重要意义;

  • SM4分组密码算法是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成;
  • SM4是一种Feistel结构的分组密码算法,其分组长度和密钥长度均为128bits。加密算法和密钥扩展算法迭代轮数均为32轮;
  • SM4加解密过程的算法相同但是轮密钥的使用顺序相反;
  • SM4密码算法使用模2加和循环移位作为基本运算;
  • 密钥扩展算法:SM4算法使用128位的加密密钥,并采用32轮迭代加密结构,每一轮加密使用一个32位的轮密钥,总共使用32个轮密钥。因此需要使用密钥扩展算法,从加密密钥中产生32个轮密钥;
  • 密钥:加密密钥的长度为128比特。

一 使用hutool实现SM4算法的封装

1. pom文件中添加依赖

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15to18</artifactId>
    <version>1.69</version>
</dependency>

 2. application.yml增加配置

#SM4配置 国密对称加密:SM4
SM4:
  key: 1234567890ABCDEF

3. 使用方式

@Value("${SM4.key}")
private String sm4Key;

SymmetricCrypto sm4 = SmUtil.sm4(sm4Key.getBytes(StandardCharsets.UTF_8));
String encryptText = sm4.encryptHex(dataText);

二 解决request流只能读取一次的问题

继承HttpServletRequestWrapper,将请求中的流copy一份,复写getInputStream和getReader方法供外部使用。每次调用后的getInputStream方法都是从复制出来的二进制数组中进行获取,这个二进制数组在对象存在期间一致存在。使用Filter过滤器,替换request为自己定义的可以多次读取流的request。

1.创建InputStreamHttpServletRequestWrapper继承HttpServletRequestWrapper

import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * InputStreamHttpServletRequestWrapper
 * 请求流支持多次获取
 **/
public class InputStreamHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 用于缓存输入流
     */
    private ByteArrayOutputStream cachedBytes;

    public InputStreamHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (cachedBytes == null) {
            // 首次获取流时,将流放入 缓存输入流 中
            cacheInputStream();
        }

        // 从 缓存输入流 中获取流并返回
        return new CachedServletInputStream(cachedBytes.toByteArray());
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }


    /**
     * 首次获取流时,将流放入 缓存输入流 中
     */
    private void cacheInputStream() throws IOException {
        // 缓存输入流以便多次读取。为了方便, 我使用 org.apache.commons IOUtils
        cachedBytes = new ByteA
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hoking

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值