sm3常量及通用函数

文章详细介绍了SM3算法实现过程中的一些关键元素,包括初始IV的宏定义,如GM_SM3_IV_A至GM_SM3_IV_H,以及Tj常量的区分定义。此外,文章还阐述了两个布尔函数FFj和GGj的实现,以及置换函数P0和P1的定义,利用循环左移操作实现。同时,提到了字与字节之间的转换函数GM_GET_UINT32_BE和GM_PUT_UINT32_BE的重要性。

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

在实现sm3算法之前,根据上述章节《sm3算法基本原理》以及sm3的规范文档,可以事先定义好一些常量及通用函数备用。

先在Clion中创建sm3.hsm3.c这两个文件。

1. 常量

1.1 初始IV

初始IV,可以用宏定义来表示,在sm3.c增加以下宏定义:

// 寄存器初始值
#define GM_SM3_IV_A 0x7380166f
#define GM_SM3_IV_B 0x4914b2b9
#define GM_SM3_IV_C 0x172442d7
#define GM_SM3_IV_D 0xda8a0600
#define GM_SM3_IV_E 0xa96f30bc
#define GM_SM3_IV_F 0x163138aa
#define GM_SM3_IV_G 0xe38dee4d
#define GM_SM3_IV_H 0xb0fb0e4e

1.2 Tj常量

在《sm3算法基本原理》的第6 -> 6.2 CF压缩函数中有用到一个Tj常量,Tj的定义如下:

TjT_jTj:是一个常量,当0≤j≤150 \leq j \leq 150j15时,它的值是0x79cc4519,当16≤j≤6316 \leq j \leq 6316j63时,它的值是0x7a879d8a

Tj也可以用宏定义来表示,同样在sm3.c中定义,不在头文件中定义,是因为其它地方不需要用到:

// Tj常量
#define GM_SM3_T_0 0x79CC4519
#define GM_SM3_T_1 0x7A879D8A

2. 布尔函数

sm3的规范中,涉及到两个布尔函数,分别是FFjGGj。对应在规范原文在《4.3 布尔函数》

2.1 FFj函数

FFj函数的定义如下:

FFj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(X∧Z)∨(Y∧Z)16≤j≤63 FF_j(X,Y,Z)= \begin{cases} X \oplus Y \oplus Z &\quad\quad 0 \leq j \leq 15 \\ (X \wedge Y) \vee (X \wedge Z) \vee (Y \wedge Z) &\quad\quad 16 \leq j \leq 63 \end{cases} FFj(X,Y,Z)={XYZ(XY)(XZ)(YZ)0j1516j63

这个公式,还是比较容易看懂,其中:

  1. ⊕\oplus:表示异或运算
  2. ∧\wedge:表示与运算
  3. ∨\vee:表示或运算

sm3.c中用宏定义来表示FFj函数,实现实现如下:

// FFj函数
#define GM_SM3_FF_0(x, y, z) ( (x) ^ (y) ^ (z) )
#define GM_SM3_FF_1(x, y, z) ( ( (x) & (y) ) | ( (x) & (z) ) | ( (y) & (z) ) )

2.2 GGj函数

GGj函数的定义如下:

GGj(X,Y,Z)={X⊕Y⊕Z0≤j≤15(X∧Y)∨(¬X∧Z)16≤j≤63 GG_j(X,Y,Z)= \begin{cases} X \oplus Y \oplus Z &\quad\quad 0 \leq j \leq 15 \\ (X \wedge Y) \vee (\neg X \wedge Z) &\quad\quad 16 \leq j \leq 63 \end{cases} GGj(X,Y,Z)={XYZ(XY)(¬XZ)0j1516j63

与FFj函数类似,只是多了一个¬\neg¬符号,它表示的是非运算。用宏定义来表示GGj函数,实现代码如下:

// GGj函数
#define GM_SM3_GG_0(x, y, z) ( (x) ^ (y) ^ (z) )
#define GM_SM3_GG_1(x, y, z) ( ( (x) & (y) ) | ( (~(x)) & (z) ) )

3. 置换函数

sm3的规范中,涉及到两个布尔函数,分别是P0P1。对应在规范原文在《4.4 置换函数》,这两个置换函数的定义如下:
P0(X)=X⊕(X⋘9)⊕(X⋘17)P1(X)=X⊕(X⋘15)⊕(X⋘23) P_0(X)=X \oplus (X \lll 9) \oplus (X \lll 17) \\ P_1(X) = X \oplus (X \lll 15) \oplus (X \lll 23) P0(X)=X(X9)(X17)P1(X)=X(X15)(X23)
其中⋘\lll表示循环左移,所以要实现这两个置换函数,首先要实现一下循环左移,循环左移的宏定义如下:

// 循环左移
#define  GM_SM3_SHL(x, n) (((x) & 0xFFFFFFFF) << (n % 32))
#define GM_SM3_ROTL(x, n) (GM_SM3_SHL((x), n) | ((x) >> (32 - (n % 32))))

3.1 P0置换函数

实现了循环左移后,再来实现P0置换函数就不难了,实现代码如下:

// P0函数
#define GM_SM3_P_0(x) ( (x) ^  GM_SM3_ROTL( (x), 9) ^ GM_SM3_ROTL( (x), 17) )

3.2 P1置换函数

// P1函数
#define GM_SM3_P_1(x) ( (x) ^  GM_SM3_ROTL( (x), 15) ^ GM_SM3_ROTL( (x), 23) )

4. 字与字节间的转换

在sm3中,字的存储是大端模式,所以要实现字与字节间的转换,实现代码如下:

// 字节转化为字
#ifndef GM_GET_UINT32_BE
#define GM_GET_UINT32_BE(n, b, off)                       \
do {                                                      \
    (n) = ( (uint32_t) (b)[(off)    ] << 24 )             \
        | ( (uint32_t) (b)[(off) + 1] << 16 )             \
        | ( (uint32_t) (b)[(off) + 2] <<  8 )             \
        | ( (uint32_t) (b)[(off) + 3]       );            \
}while(0)
#endif

// 字转化为字节
#ifndef GM_PUT_UINT32_BE
#define GM_PUT_UINT32_BE(n, b ,off)                       \
do {                                                      \
    (b)[(off)    ] = (unsigned char) ( (n) >> 24 );       \
    (b)[(off) + 1] = (unsigned char) ( (n) >> 16 );       \
    (b)[(off) + 2] = (unsigned char) ( (n) >>  8 );       \
    (b)[(off) + 3] = (unsigned char) ( (n)       );       \
}while(0)
#endif

其中参数n为字变量,参数b为字节变量,off表示字节变量b的偏移量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值