说明,此文章为C开发的SM3.c文件,没有使用第三方密码库,如果不足,欢迎指出
/************************************************************
版权声明:
文件名称: SM3.c
文件描述: 包括了实现SM3的相关常量、函数和其他定义
创 建 者: 程帅
创建时间:2023/7/18
修改历史:
*********************************************************************/
#include "SM3.h"
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
static uint32_t globalIV[8] = { 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa,
0xe38dee4d, 0xb0fb0e4e };//常量
//字结构体,包含了W和W'
struct myWord {
uint32_t W[68];
uint32_t W1[64];
};
/********************************************************************************
函 数 名:Conver
说 明 : 大小端转化
功能描述:对4字节的数进行大小的转化
参数:
value(in)待转化的字节
返 回 值 : 逆向大小端的四字节
********************************************************************************/
#define Conver(value) ((((value) & 0x000000FFU) << 24 | ((value) & 0x0000FF00U) << 8 |((value) &\
0x00FF0000U) >> 8 | ((value) & 0xFF000000U) >> 24))
/********************************************************************************
函 数 名:ROTATE_LEFG
说 明 : 循环左移
功能描述:对4字节的数进行大小的转化
参数:
a(in)要循环左移的字
k(in)左移的次数
返 回 值 : 左移k次的字
********************************************************************************/
#define ROTATE_LEFG(a, k) (((a) << (k)) | ((a) >> (32 - (k))))
/*******************************************************************************
函 数 名:T
说 明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
返 回 值 : 相应的常量
*******************************************************************************/
#define T(j) (j) <= 15 ? 0x79cc4519 : 0x7a879d8a
/*******************************************************************************
函 数 名 FF
说 明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
x(in)字X
y(in)字Y
z(in)字Z
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define FF( j, x, y, z) ((j) <= 15 ? (x) ^ (y) ^ (z) : ((x) & (y)) | ((x) & (z)) | ((y) & (z)))
/*******************************************************************************
函 数 名 GG
说 明 :
功能描述:根据j输出相应的常量 参数
参数:
j(in)次数
x(in)字X
y(in)字Y
z(in)字Z
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define GG(j, x, y, z) ((j) <= 15 ? (x) ^ (y) ^ (z) : ((x) & (y)) | (~(x) & (z)) )
/*******************************************************************************
函 数 名:DISPLACE_0
说 明 : 置换函数0
功能描述:对字x进行固定的计算
参数:
x(in)字X
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define DISPLACE_0(X) ((X) ^ (ROTATE_LEFG((X), 9)) ^ (ROTATE_LEFG((X), 17)))
/*******************************************************************************
函 数 名:DISPLACE_0
说 明 : 置换函数1
功能描述:对字x进行固定的计算
参数:
x(in)字X
返 回 值 : 逻辑运算后的字
*******************************************************************************/
#define DISPLACE_1(X) ((X) ^ (ROTATE_LEFG((X), 15)) ^ (ROTATE_LEFG((X), 23)))
/*******************************************************************************
函 数 名:bitStuffing
说 明 : 比特填充
功能描述:将message需要填充的部分放入stuffFinBlock中,并对stuffFinBlock进行填充
参数:
*message(in)消息
len(in)消息长度
*stuffFinBlock(out)填充后的消息
返 回 值 :
*******************************************************************************/
void bitStuffing(uint8_t* message, uint64_t len, uint8_t* stuffFinBlock)
{
uint8_t* finBlock;/*用来存储消息的末尾数据*/
uint8_t emptyBlock[64];/*一个空块,当末尾数据为空时,使用该块*/
uint8_t temp;/*存储大小端转化时的中间变量*/
uint64_t bitLen = len * 8;/*存储消息长度的比特大小*/
/*判断消息是否为整块512比特,即消息的末尾数据是否为空*/
if (0 != len % 64) {
/*非整块则获得原有最有一块消息的数据*/
uint64_t suffLen = (len / 64) * 64;
finBlock = message + suffLen;
}
else {
/*整块则使用一个新的空消息块*/
finBlock = emptyBlock;
}
/*填充'0'和消息*/
memset(stuffFinBlock, 0, 64);
memcpy(stuffFinBlock, finBlock, len % 64);
/*填充'1'*/
*(stuffFinBlock + (len % 64)) = 0b10000000;
/*填充'消息长度'*/
memcpy(stuffFinBlock + 64 - 8, (uint8_t *)&bitLen, 8);
/*小字节转大字节,大小端转化开始*/
for (int i = 1; i <= 4; i++) {
temp = stuffFinBlock[64 - i];
stuffFinBlock[64 - i] = stuffFinBlock[64 - 9 + i];
stuffFinBlock[64 - 9 + i] = temp;
}/*大小端转化结束*/
}
/*******************************************************************************
函 数 名: MessExtension
说 明 : 消息扩展
功能描述:对消息message进行字扩展,扩展后的字将放入myW中
参数:
*message(in)消息
*W(in)扩展字W
*W1(in)扩展字W'
返 回 值 : 0成功,-1失败
*******************************************************************************/
int MessExtension(uint8_t* message, uint32_t* W, uint32_t* W1)
{
uint8_t temp;/*存储大小端转化时的中间变量*/
uint8_t mess_copy[64];/*存储消息副本*/
/*消息拷贝*/
memcpy(mess_copy, message, 64);
/*扩展字W填充结束*/
/*1.大小端转化和拷贝字开始*/
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 2; j++) {
temp = mess_copy[i * 4 + j];
mess_copy[i * 4 + j] = mess_copy[i * 4 + 4 - 1 - j];
mess_copy[i * 4 + 4 - 1 - j] = temp;
}
memcpy(W + i, mess_copy + i * 4, 4);/*4个一字节拷入1个四字节*/
}/*1.大小端转化和拷贝字结束*/
/*2.扩展字W计算结束*/
for (int j = 16; j <= 67; j++) {
W[j] = DISPLACE_1(W[j - 16] ^ W[j - 9] ^ (ROTATE_LEFG(W[j - 3], 15))) ^ (ROTATE_LEFG(W[j - 13], 7)) ^ W[j - 6];
}/*2.扩展字W计算结束*/
/*扩展字W填充结束*/
/*扩展字W'填充开始*/
for (int j = 0; j <= 63; j++) {
W1[j] = W[j] ^ W[j + 4];
}/*扩展字W'填充结束*/
return 0;
}
/*******************************************************************************
函 数 名: CF
说 明 : 压缩函数
功能描述:利用扩展字myW对向量IV进行压缩,结构输出到IV中,参数(输入向量,扩展字)
参数:
*IV(in)输入向量
*W(in)扩展字W
*W1(in)扩展字W'
返 回 值 :
*******************************************************************************/
void CF(uint32_t* V, uint32_t* W, uint32_t* W1)
{
/*初始化初始向量*/
uint32_t A = V[0];
uint32_t B = V[1];
uint32_t C = V[2];
uint32_t D = V[3];
uint32_t E = V[4];
uint32_t F = V[5];
uint32_t G = V[6];
uint32_t H = V[7];
/*初始化中间值*/
uint32_t SS1, SS2, TT1, TT2;
/*中间值计算开始*/
for (int j = 0; j <= 63; j++) {
SS1 = ROTATE_LEFG(ROTATE_LEFG(A, 12) + E + ROTATE_LEFG(T(j), j), 7);
SS2 = SS1 ^ ROTATE_LEFG(A, 12);
TT1 = FF(j, A, B, C) + D + SS2 + W1[j];
TT2 = GG(j, E, F, G) + H + SS1 + W[j];
D = C;
C = ROTATE_LEFG(B, 9);
B = A;
A = TT1;
H = G;
G = ROTATE_LEFG(F, 19);
F = E;
E = DISPLACE_0(TT2);
}/*中间值计算结束*/
/*结果运算*/
V[0] = A ^ V[0];
V[1] = B ^ V[1];
V[2] = C ^ V[2];
V[3] = D ^ V[3];
V[4] = E ^ V[4];
V[5] = F ^ V[5];
V[6] = G ^ V[6];
V[7] = H ^ V[7];
}
/*******************************************************************************
函 数 名:iteration
说 明 : 迭代过程
功能描述:对message进行迭代处理,其中包括对message经行扩展和压缩
参数:
*message(in)消息
n(in)消息块数
*hash(out)杂凑值
返 回 值 : 0成功,-1失败
*******************************************************************************/
int iteration(uint8_t* message, int n, uint32_t* hash)
{
uint32_t V[8];/*存储每一组计算完的向量值*/
uint8_t messageBlk[64];/*存储消息快*/
struct myWord myW;
/*初始化向量*/
memcpy(V, globalIV, 32);
/*迭代运算开始*/
for (int i = 0; i <= n; i++) {
/*拷贝消息*/
memcpy(messageBlk, message + i * 64, 64);
/*扩展*/
MessExtension(messageBlk, myW.W, myW.W1);
/*压缩*/
CF(V, myW.W, myW.W1);
}/*迭代运算结束*/
/*将结果拷贝给hash作为输出*/
memcpy(hash, V, 32);
return 0;
}
/*******************************************************************************
函 数 名:SM3Hash
说 明 : SM3接口函数
功能描述:对输入的数据mess进行SM3杂凑值提取
参数:
mess(in)待处理的消息
len(in) 消息长度(字节)
hash(out)杂凑值
返 回 值 : -1失败 0成功
*******************************************************************************/
int SM3Hash(uint8_t* mess, uint64_t len, uint8_t* hash)
{
uint8_t* mess_copy;/*消息的拷贝*/
uint8_t stuffFinBlock[64];/*填充的块*/
uint32_t hashValue[8];/*存储迭代的中间哈希值*/
const int n = (int)len / 64;/*消息的分组个数*/
/*拷贝原有的消息内容*/
uint64_t maxLen = ((uint64_t)n + 1) * 64;/*消息填充后的最大长度*/
mess_copy = malloc((size_t)maxLen);
if (NULL == mess_copy) {
return -1;
}
/*拷贝消息到局部副本*/
memset(mess_copy, 0, (size_t)maxLen);
memcpy(mess_copy, mess, (size_t)len);
/*消息填充*/
bitStuffing(mess_copy, len, stuffFinBlock);
memcpy(mess_copy + n * 64, (uint8_t*)stuffFinBlock, 64);
/*开始迭代*/
iteration(mess_copy, n, hashValue);
/*大小端处理开始*/
for (int i = 0; i < sizeof(hashValue) / 4; i++) {
hashValue[i] = Conver(hashValue[i]);
}/*大小端处理结束*/
/*将杂凑值拷贝到输出*/
memcpy(hash, hashValue, 32);
/*释放内存*/
free(mess_copy);
mess_copy = NULL;
return 0;
}