SM4算法简介
Posted m0_74043383
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SM4算法简介相关的知识,希望对你有一定的参考价值。
SM4为分组对称密码算法,明文、密文以及密钥长度均为
128
128
128 bits。SM4算法主要包括加解密算法和密钥扩展算法,采用
32
32
32 轮非线性迭代的数学结构,其中算法中每一次迭代运算为一轮非线性变换。主要操作包括异或、合成置换、非线性迭代、反序变换、循环移位以及S盒变换等。加密算法和解密算法的数学架构、运算法则、运算操作等都是完全相同的,解密运算只需要将加密算法中生成的轮密钥进行反序使用。其流程图如下图所示。
图1. SM4密码算法加密流程图
密钥扩展算法
设加密主密钥
M
K
=
(
M
K
0
,
M
K
1
,
M
K
2
,
M
K
3
)
MK = (MK_0, MK_1, MK_2, MK_3)
MK=(MK0,MK1,MK2,MK3),
M
K
i
∈
0
,
1
32
MK_i \\in \\0,1\\^32
MKi∈0,132
(
K
0
,
K
1
,
K
2
,
K
3
)
=
(
M
K
0
⊕
F
K
0
,
M
K
1
⊕
F
K
1
,
M
K
2
⊕
F
K
2
,
M
K
3
⊕
F
K
3
)
(K_0,K_1,K_2, K_3) = (MK_0 \\oplus FK_0, MK_1 \\oplus FK_1, MK_2 \\oplus FK_2, MK_3 \\oplus FK_3)
(K0,K1,K2,K3)=(MK0⊕FK0,MK1⊕FK1,MK2⊕FK2,MK3⊕FK3)
r
k
i
=
K
i
+
4
=
K
i
⊕
T
′
(
K
i
+
1
⊕
K
i
+
2
⊕
K
i
+
3
⊕
C
K
i
)
rk_i = K_i+4 = K_i \\oplus T^'(K_i+1 \\oplus K_i+2 \\oplus K_i+3 \\oplus CK_i)
rki=Ki+4=Ki⊕T′(Ki+1⊕Ki+2⊕Ki+3⊕CKi)
T ′ T^' T′变换
T ′ ( B ) = B ⊕ ( B < < < 13 ) ⊕ ( B < < < 23 ) T^'(B) = B \\oplus (B <<< 13) \\oplus (B <<< 23) T′(B)=B⊕(B<<<13)⊕(B<<<23)
系统参数 F K FK FK
F K i FK_i FKi | 十六进制取值 |
---|---|
F K 0 FK_0 FK0 | A3B1BAC6 |
F K 1 FK_1 FK1 | 56AA3350 |
F K 2 FK_2 FK2 | 677D9197 |
F K 3 FK_3 FK3 | B27022DC |
固定参数 C K CK CK
固定参数 CK 的取值 | |||
000070e15 | 1c232a31 | 383f464d | 545b6269 |
70777e85 | 8c939aa1 | a8afb6bd | c4cbd2d9 |
e0e7eef5 | fc030a11 | 181f262d | 343b4249 |
50575e65 | 6c737a81 | 888f969d | a4abb2b9 |
c0c7ced5 | dce3eaf1 | f8ff060d | 141b2229 |
3037aeb5 | 4c535a61 | 686f767d | 848b9299 |
a0a7aeb5 | bcc3cad1 | d8dfe6ed | f4fb0209 |
10171e25 | 2e333a41 | 484f565d | 646b7279 |
加解密算法
设输入明文为:
(
X
0
,
X
1
,
X
2
,
X
3
)
∈
0
,
1
32
×
4
(X_0, X_1, X_2, X_3) \\in \\0,1\\^32 \\times 4
(X0,X1,X2,X3)∈0,132×4, 密文输出为:
(
Y
0
,
Y
1
,
Y
2
,
Y
3
)
∈
0
,
1
32
×
4
(Y_0, Y_1, Y_2, Y_3) \\in \\0,1\\^32 \\times 4
(Y0,Y1,Y2,Y3)∈0,132×4, 轮密钥
r
k
i
∈
0
,
1
32
×
4
rk_i \\in \\0,1\\^32 \\times 4
rki∈0,132×4, 其中
i
∈
0
,
1
,
⋯
31
i \\in \\0,1,\\cdots 31\\
i∈0,1,⋯31.SM4密码算法的具体加密过程如下:
X
i
+
1
=
F
(
X
i
,
X
i
+
1
,
X
i
+
2
,
X
i
+
3
,
r
k
i
)
=
X
i
⊕
T
(
X
i
+
1
⊕
X
i
+
2
⊕
X
i
+
3
⊕
r
k
i
)
X_i+1 = F(X_i, X_i+1, X_i+2, X_i+3, rk_i)=X_i\\oplus T(X_i+1\\oplus X_i+2\\oplus X_i+3\\oplus rk_i)
Xi+1=F(Xi,Xi+1,Xi+2,Xi+3,rki)=Xi⊕T(Xi+1⊕Xi+2⊕X目录
简介
项目中要求密码加密算法使用国家的密码标准SM4.0,下面来介绍下。
SM4算法是我国发布的商用密码算法中的分组密码算法,是一种迭代分组密码算法,由加解密算法和密钥扩展算法组成。其分组长度和密钥长度均为128比特,加密算法和密钥扩展算法迭代轮数均为32轮。SM4加解密过程的算法相同但是轮密钥的使用顺序相反。SM4算法具有安全高效的功能特点,在设计和实现方面具有一定的优势。
项目集成
在项目中登录以及鉴权使用的是Spring Security,与框架的集成如下。
引入依赖
首先需要引入如下两个依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>$hutool.version</version>
</dependency>
<!-- 加密解密包 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>$bcprov.version</version>
</dependency>
测试
工具类中可以使用如下方法自行测试加密效果
public static void main(String[] args)
try
//自定义秘钥
String key = "6gsx@654hs68456!";
String password="123456";
SymmetricCrypto crypto = SmUtil.sm4(key.getBytes());
String s2 = crypto.encryptHex(password);
String s3 = crypto.decryptStr(s2);
System.out.println(s2);
System.out.println(s3);
//用工具类生成,此处使用随机秘钥,加解密需要使用同一个示例才可得到原始密码
SM4 sm4 = SmUtil.sm4();
catch (Exception e)
throw new RuntimeException(e);
编写 PasswordEncoder
Spring Security默认支持的密码算法如下:
public static PasswordEncoder createDelegatingPasswordEncoder()
String encodingId = "bcrypt";
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put(encodingId, new BCryptPasswordEncoder());
encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256",
new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
return new DelegatingPasswordEncoder(encodingId, encoders);
在我们集成登录时候,会将登录的密码与用户的密码作比较,因此我们需要自定义一个新的PasswordEncoder来替换掉默认的。
定义SM4PasswordEncoder
public class SM4PasswordEncoder implements PasswordEncoder
private final SymmetricCrypto sm4;
public SM4PasswordEncoder(String key)
SymmetricCrypto crypto = SmUtil.sm4(key.getBytes());
this.sm4 = crypto;
@Override
public String encode(CharSequence rawPassword)
return sm4.encryptHex(rawPassword.toString());
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword)
return sm4.encryptHex(rawPassword.toString()).equals(encodedPassword);
matches方法即会在登录时调用此方法比较。
配置文件定义
因为我们需要自定义一个加密的秘钥,在实际项目中我们根据实际情况灵活配置,所以我们定义一个配置文件 application-sm4.yml
te
system:
sm4-key: z^cnmuop2372a375
注意: key的秘钥位数需要是 16因为 128位/8 = 16
properties类
@Data
@Component
@ConfigurationProperties(prefix = "te.system")
public class SystemEnvProperties
@NotNull
@ApiModelProperty(notes = "sm4加密秘钥-需要16byte")
private String sm4Key;
注册为Bean
/**
* 密码明文加密方式配置(使用国密SM4)
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(SystemEnvProperties envProperties)
return new SM4PasswordEncoder(envProperties.getSm4Key());
密码加密
在创建用户及修改密码时候,调用加密方法
@Autowired
private PasswordEncoder passwordEncoder;
userInfo.setPassword(passwordEncoder.encode(vo.getPassword()));
至此,集成完成
以上是关于SM4算法简介的主要内容,如果未能解决你的问题,请参考以下文章
密码算法(SM1SM2SM3SM4同态加密密态计算隐私计算和安全多方计算)