SM3杂凑算法是我国自主设计的密码杂凑算法
SM3是中华人民共和国政府采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。
在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。
完整源码下载地址:https://download.csdn.net/download/guoggn/18439171
一、 处理过程
1、分组
512bit为一组,
2、填充
不够512bit进行填充,假设消息m 的长度为l 比特。首先将比特“ 1”添加到消息的末尾,再添加k 个“ 0”, k是满
足l + 1 + k ≡ 448mod512 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度l的二进
制表示。填充后的消息m′ 的比特长度为512的倍数
3、消息扩展
4、迭代压缩
二、c51代码
/* 压缩函数 */
void CF(u8 *arr)
{
u32 j;
u32 A, B, C, D, E, F, G, H;
u32 SS1, SS2, TT1, TT2;
#ifdef _DEBUG
printf("message = \n");
for (j = 0; j < 64; j++)
printf("%b02x", arr[j]);
printf("\n\n");
#endif
/* 消息扩展 */
for (j = 0; j < 16; j++)
{
W[j] = (u32)arr[j * 4 + 0] << 24 | (u32)arr[j * 4 + 1] << 16 | (u32)arr[j * 4 + 2] << 8 | (u32)arr[j * 4 + 3];
}
for (j = 16; j < 68; j++)
{
W[j] = P_1(W[j - 16] ^ W[j - 9] ^ (rotate_left(W[j - 3], 15))) ^ (rotate_left(W[j - 13], 7)) ^ W[j - 6];
}
#ifdef _DEBUG
printf("W[] = \n");
for (j = 0; j < 68; j++)
printf("%l08x, ", W[j]);
printf("\n\n");
#endif
for (j = 0; j < 64; j++)
{
W_1[j] = W[j] ^ W[j + 4];
}
#ifdef _DEBUG
printf("W_1[] = \n");
for (j = 0; j < 64; j++)
printf("%l08x, ", W_1[j]);
printf("\n\n");
#endif
/* 消息压缩 */
A = hash[0];
B = hash[1];
C = hash[2];
D = hash[3];
E = hash[4];
F = hash[5];
G = hash[6];
H = hash[7];
for (j = 0; j < 64; j++)
{
#ifdef _DEBUG
printf("A_[%l02d] = %l08x, %l08x, %l08x, %l08x, %l08x, %l08x, %l08x, %l08x \n", j, A,B,C,D,E,F,G,H);
#endif
SS1 = rotate_left((rotate_left(A, 12)) + E + (rotate_left(T[j], j)), 7);
SS2 = SS1 ^ (rotate_left(A, 12));
TT1 = FF(A, B, C, j) + D + SS2 + W_1[j];
TT2 = GG(E, F, G, j) + H + SS1 + W[j];
D = C;
C = rotate_left(B, 9);
B = A;
A = TT1;
H = G;
G = rotate_left(F, 19);
F = E;
E = P_0(TT2);
}
#ifdef _DEBUG
printf("A_[%l02d] = %l08x, %l08x, %l08x, %l08x, %l08x, %l08x, %l08x, %l08x \n", j, A,B,C,D,E,F,G,H);
#endif
hash[0] = (A ^ hash[0]);
hash[1] = (B ^ hash[1]);
hash[2] = (C ^ hash[2]);
hash[3] = (D ^ hash[3]);
hash[4] = (E ^ hash[4]);
hash[5] = (F ^ hash[5]);
hash[6] = (G ^ hash[6]);
hash[7] = (H ^ hash[7]);
}
void SM3(u8 *msg, u32 msglen, u8 *out_hash)
{
u32 i, bitLen, remainder;
/* 初始化上下文 */
SM3_Init();
/* 消息分组处理 */
for(i = 0; i < msglen/64; i++){
memcpy(message_buffer, msg + i * 64, 64);
CF(message_buffer);
}
/* 分组信息部分不够64字节,填充消息,并处理 */
bitLen = msglen * 8;
remainder = msglen % 64;
memcpy(message_buffer, msg + i * 64, remainder);
memset(&message_buffer[remainder], 0, 64 - remainder);
message_buffer[remainder] = 0x80;
/* 信息部分小于55字节,填充部分大于8字节 */
if(remainder <= 55)
{
/* 长度按照大端法占8个字节,消息块为64字节,故填充的长度高 4 个字节恒为 0 */
memcpy(message_buffer + 60, &bitLen, 4);
CF(message_buffer);
}
/* 信息部分大于55字节,填充部分不够8字节 ,将长度串放入下一分组进行压缩*/
else
{
CF(message_buffer);
memset(message_buffer, 0, 64);
memcpy(message_buffer + 60, &bitLen, 4);
CF(message_buffer);
}
/* 返回结果 */
memcpy(out_hash, hash, 32);
#ifdef _DEBUG
printf("hash[] = \n");
for (i = 0; i < 32; i++)
printf("%b02x", out_hash[i]);
printf("\n");
#endif
}
void sm3test(void)
{
s32 i,len;
u8 Hash[32]={0};
s8 str[]="abc";
//66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
s8 str2[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
//debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
printf("in = \"%s\"\r\n",str);
len=strlen(str);
SM3(str, len, Hash);
printf("out = ");
for (i = 0; i < 32; i++)
printf("%b02x", Hash[i]);
printf("\n\n");
printf("in = \"%s\"\r\n",str2);
len=strlen(str2);
SM3(str2, len, Hash);
printf("out = ");
for (i = 0; i < 32; i++)
printf("%b02x", Hash[i]);
printf("\n");
}
下载全部源码
https://download.csdn.net/download/guoggn/18439171
参考
https://blog.csdn.net/weixin_48203710/article/details/106409587