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);}@Overridepublic ServletInputStream getInputStream() throws IOException {if (cachedBytes == null) {// 首次获取流时,将流放入 缓存输入流 中cacheInputStream();}// 从 缓存输入流 中获取流并返回return new CachedServletInputStream(cachedBytes.toByteArray());}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}/*** 首次获取流时,将流放入 缓存输入流 中*/private void cacheInputStream() throws IOException {