SM4国密算法实现分析
来源:互联网 发布:软件开发公司名字 编辑:程序博客网 时间:2024/05/31 06:22
SM4的说明(pdf):http://download.csdn.net/detail/leechiyang/5008528
算法调用参数
该算法需要一个结构体 sm4_context ctx 来保存上下文信息,即加密模式和各轮子密钥。
该结构体定义如下:
- 1
- 2
- 3
- 4
- 5
- 6
加密
密钥调度算法
首先调用sm4_setkey_enc(&ctx,key)设置密钥,这个函数会设置mode为加密,并调用static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )来完成设置密钥的操作:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
类似于加密中的操作,首先通过宏将初始的密钥转换为4个32位bit整数,MK0,MK1,MK2,MK3,并为计算各轮密钥预先准备好初始值,其中FK数组为系统参数:
- 1
- 2
- 3
- 4
此后,对于第i轮的密钥SK[i] ,其是由k[i]和对k[i+1]^k[i+2]^k[i+3]^CK[i]的复合变换T’异或得到的:
SK[i] = k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i]))
其中CK是固定参数,虽然代码中直接给出了CK,实际上,其是有一定的计算方法的:设CKij为CKi的第j字节,即CKi=(cki0, cki1, cki2, cki3),则ckij=(4i+j)*7(mod 256)。
函数sm4CalciRK,也就是变换T’,与加密轮函数中的T基本相同,同样是先进行Sbox的非线性替换,然后进行线性变换,只是线性变换L改为了:
rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
加密过程
通过调用void sm4_crypt_ecb( sm4_context *ctx,int mode,int length,unsigned char *input,unsigned char *output)对密文input进行电码本模式的加密,加密的核心是调用了 对每一块密文进行加密:static void sm4_one_round( unsigned long sk[32], unsigned char input[16], unsigned char output[16]):
- 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
函数中使用了两个宏GET_ULONG_BE(n,b,i)和PUT_ULONG_BE(n,b,i),作用分别为:
GET_ULONG_BE(n,b,i):将字符型数组b的第i到第i+3位的二进制拼接成一个4*8=32bit的整数,存入n中
- 1
- 2
- 3
- 4
- 5
- 6
- 7
PUT_ULONG_BE(n,b,i):将整数n的32位的二进制表示转换为4个char的数组,存入数组b的第i到第i+3位
- 1
- 2
- 3
- 4
- 5
- 6
- 7
所以,在函数sm4_one_round()中,先将128位的输入input转为四个32位的整数,放入ulbuf[4]中,然后迭代地调用函数static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk) 进行32轮加密,每一轮加密都需要使用之前的128位结果 ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3] 和该轮的密钥 sk[i],产生出该轮的密文 ulbuf[i+4],最后的密文存储在ulbuf[35]~ulbuf[32]中,转换为字符数组的形式放入output中。
一轮加密static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
- 1
- 2
- 3
- 4
每一轮加密中,输入为(x0, x1, x2, x3),xi为32位比特,共计128比特。通过x0^sm4Lt(x1^x2^x3^rk)
得到该轮加密的结果。在此时,SM4就将轮密钥应用在了加密中。
sm4Lt()是一个合成变换,由非线性变换t和线性变换L复合而成:
首先将输入的整数ka转换为8比特一个的字符PUT_ULONG_BE(ka,a,0)
,然后使用S盒进行非线性变换,再将变换结果转换为32比特的整数GET_ULONG_BE(bb,b,0)
,最后对得到的32位整数bb进行线性变换:
c=bb异或(bb<<<2)异或(bb<<<10)异或(bb<<<18)异或(bb<<<24)。从而得到复合变换的结果c。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
算法中对循环移位的实现较为巧妙:
- 1
- 2
SHL(x,n)可以得到左移n位之后的结果,然后与右移的结果((x) >> (32 - n))逐位或来将右边空缺的n位补齐,效率比较高。
加密过程小结
至此,sm4算法的加密过程就分析完了。其加密过程与DES算法相似,每一轮中先使用sbox进行非线性变换,然后再通过循环移位操作进行线性变换。其每轮加密用到了之前四轮加密的结果,进一步提高了加密的强度。
解密过程
解密前,首先要通过void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] )函数设定解密时使用的key,这个函数还会将密钥的顺序倒置,然后调用sm4_crypt_ecb()即可解密。
实际上,SM4的解密变换与加密变换结构相同,不同的仅仅是轮密钥的使用顺序相反。
转自:http://blog.csdn.net/archimekai/article/details/53095993
- SM4国密算法实现分析
- SM4国密算法实现分析
- PHP实现国密算法SM4
- 关于国密算法SM4的流程
- 国密算法SM4,3DES算法和AES三种加密算法的java实现
- spring集成shiro实现登录认证自定义验证功能(认证采用国密SM4算法)
- 国家密码算法SM4(国密算法)介绍
- 关于国密算法 SM1,SM2,SM3,SM4 的笔记
- 关于国密算法 SM1,SM2,SM3,SM4 的笔记
- 关于国密算法 SM1,SM2,SM3,SM4 的笔记
- 关于国密算法 SM1,SM2,SM3,SM4 的笔记
- 分组密码SM4算法的代码实现
- 国密算法(SM2,SM3,SM4)完善与算法辅助工具开发
- 国密算法(SM2,SM3,SM4)完善与算法辅助工具开发
- java实现基于SM4算法计算联机MAC数据
- 国密算法(SM2,SM3,SM4)辅助工具升级版(OTP+PBOC3.0)
- 国密算法(SM2,SM3,SM4)辅助工具升级版(OTP+PBOC3.0)
- 【国密算法那点事儿】解读DES和SM4、RSA和SM2及SM3
- 【SQL Server DBA】日常巡检语句3:特定监控(阻塞、top语句、索引、作业)
- mybatis使用foreach
- 第十二周项目五——拓扑排序算法验证
- mt2523Flash tool 是否支援 UART download?
- 【c#系列 四】从java到.net 核心
- SM4国密算法实现分析
- Unity 生成WebGL时UI界面随浏览器自适应
- 解决遇到动态加载jar安全的问题。
- PHP-TP微信公众号接入微信分享
- 日请求过亿的Web系统PHP7升级实践
- C/C++的注释规范
- POJ 3723 Conscription (Kruskal并查集求最小生成树)
- 机器学习保险行业问答开放数据集: 2. 使用案例
- LeetCode 之 Multiply Strings