复盘最近工作遇到的国密sm4解密,花费了不少精力才解决。
打开ai搜索引擎,初步了解什么是国密sm4。输出了以下内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
国密SM4算法概述
国密SM4算法是中国国家密码管理局发布的商用密码算法标准,是一种对称分组加密算法。SM4算法主要用于数据的加密和解密,其设计目的是为了替代国际上广泛使用的DES和AES算法,以提高国内信息安全系统的自主可控性。
算法特点
密钥长度和分组长度:
SM4算法的密钥长度为128位,与AES算法相同,这一长度的密钥足以提供较高的安全性。
分组长度也为128位,即16字节。
结构:
SM4算法采用32轮迭代的非平衡Feistel结构,每一轮需要一个轮密钥。
加密和解密过程使用相同的算法,唯一的不同在于解密密钥是由加密密钥生成的。
核心操作:
异或操作:将轮密钥与输入数据进行异或运算。
移位操作:循环左移。
S盒变换:将8位输入映射到8位输出的固定变换,用于实现非线性变换。
加密过程
初始向量:
明文数据首先与初始向量进行异或运算。
轮函数:
轮函数包括32次迭代运算。
每一轮运算包括一个轮密钥加运算和四个S盒查找运算。
轮密钥加运算是将轮密钥与输入数据进行异或运算。
S盒查找运算是将数据通过S盒进行非线性变换。
输出密文:
经过32轮迭代运算后,输出密文。
解密过程
初始向量:
密文数据首先与初始向量进行异或运算。
轮函数:
解密过程与加密过程程类似,只是轮密钥的使用顺序相反。
输出明文:
经过32轮迭代运算后,输出明文。
安全性
SM4算法的安全性主要体现在以下几个方面:
密钥长度:128位的密钥长度提供了较高的安全性。
非线性变换:S盒变换引入了非线性,增加了算法的复杂度,提高了抗攻击能力。
迭代次数:32轮迭代使得攻击者难以通过简单的线性或差分攻击破解算法。
应用场景
SM4算法广泛应用于各种信息安全领域,包括但不限于:
数据加密:保护敏感数据的传输和存储。
网络通信:确保网络通信的安全性。
安全协议:如SSL/TLS协议中的加密算法。
总结
国密SM4算法作为一种高效的对称分组加密算法,凭借其较高的安全性和灵活性,在国内信息安全领域得到了广泛的应用。随着国密算法的普及,SM4算法在保障国家网络安全和推动信息产业自主可控方面将发挥越来越重要的作用。
|
通过上面内容,对国密有了一个初步的了解,该算法主要在国内使用,对标国际AES和DES加密算法。
现在说下我目前的信息,base64形式加密串、IV、TAG、以及密钥,它是国密sm4,带着这些在搜哟引擎找到了https://github.com/tjfoc/gmsm/blob/master/sm4/sm4_gcm_test.go
,随后和对接方确认是sm4-gcm加密的,测试发现并无法实现解密,执行还会报错,怀疑是否是姿势不对,将参数调整一番仍然不行。
接着再和需求方沟通,同步无法解密的情况,也将代码也发送了过去,我说了这里用的一个开源库来解密的,对方还很吃惊,此时还没意识到问题在哪,无果。内部同时沟通一番,以前做过类似的解密,但是用的cpp,golang并没有用过,并给了一个cpp解密方法,成功解密。
这令我很好奇,步骤几乎一样,在golang竟然无法解密,有了对比就看差异了,两边源码都是有的。下面是go的一个目录。
1
2
3
4
5
6
7
8
9
|
sm4
├── lib
│ ├── sm4.h
│ └── sm4.a
├── sm4.go
├── sm4_gcm.go
├── sm4_gcm_test.go
├── sm4_test.go
└── utils.go
|
在cpp目录下也找到了sm4和sm4.a,通过阅读两边源码发现代码并没有加解密处理的逻辑,都是调用了静态库,对比下md5值,果然发现是不一样的。替换成cpp的这个版本后,解密成功。
后面了解到公司内部自己编译了一个国密版本,外面的开源版本并不能实现解密,当时也在内部社区进行了查阅,都是在讲实现原理,加解密例子,并无法获得有效信息(也许当时仔细看看也能看出问题)。
总结:
- 版本是否一致
- 了解原理,公司内部是否有特殊性
- 让对接方提供对应语言的解密示例或者sdk
- 快速找到能解密和不能解密的例子,查看实现源码