1. 简介
SM3:
- 国家密码管理局于2010年12月发布
- 国标GB/T 32905-2016
- 强度大概等同于SHA-256
- 大端存储
- 消息长度:<264 bits
- 字长:4 bytes
- Hash长度:256 bits == 32 bytes
- 轮数:64
2. 常数与函数
初始值
static const uint32_t IV[8] = {
0x7380166f,
0x4914b2b9,
0x172442d7,
0xda8a0600,
0xa96f30bc,
0x163138aa,
0xe38dee4d,
0xb0fb0e4e
};
常量
// T[ j < 16 ? 0 : 1 ]
static const uint32_t T[2] =
{
0x79CC4519, 0x7A879D8A
};
布尔函数
static uint32_t FF(uint32_t x, uint32_t y, uint32_t z, uint32_t j)
{
// 0 <= j <= 15
if (j < 16)
{
return x ^ y ^ z;
}
// 16 <= j <= 63
else
{
return (x & y) | (x & z) | (y & z);
}
}
static uint32_t GG(uint32_t x, uint32_t y, uint32_t z, uint32_t j)
{
// 0 <= j <= 15
if (j < 16)
{
return x ^ y ^ z;
}
// 16 <= j <= 63
else
{
return (x & y) | (~x & z);
}
}
置换函数
static uint32_t P0(uint32_t x)
{
return x ^ ROTL(x, 9) ^ ROTL(x, 17);
}
static uint32_t P1(uint32_t x)
{
return x ^ ROTL(x, 15) ^ ROTL(x, 23);
}
3. 算法描述
输入:<264 bits
流程:
- 填充
- 迭代压缩
输出:32 bytes
填充
与SHA1完全相同。
第一步,填充数据,使位长度比512的倍数小64。
bitsLen == 448 mod 512
bytesLen == 56 mod 64
填充方法:
- 一个1,后续用0;
- 至少填充1 bit,至多512 bits (64 bytes)。
第二步,添加64 bits消息长度。
经过这一步,消息长度就是512 bits (16 words)的倍数了。
迭代
将填充后的数据M分为N个长512 bit的分组(block)。
for(i = 0 ; i < N; ++i)
{
// V[0] = 256-bit IV
// CF: Compression Function
V[i+1] = CF(V[i], M[i]);
}
扩展
已知每个消息分组为512 bits == 64 bytes == 16 words(uint32)。在代码中,正是以16个4字节整型为单位进行处理的。
这一步是将16个字扩展为132个字:W0 W1...W67 W'0 ... W'63
uint32_t W[HASH_ROUND_NUM + 4] = {0};
uint32_t W1[HASH_ROUND_NUM] = {0};
// extend W[16:68]
for (j = 16; j < (HASH_ROUND_NUM + 4); j++)
{
W[j] = P1(
W[j - 16]
^ W[j - 9]
^ ROTL(W[j - 3], 15)
)
^ ROTL(W[j - 13], 7)
^ W[j - 6];
}
// extend W[68:132] == W1
for (j = 0; j < HASH_ROUND_NUM; j++)
{
W1[j] = W[j] ^ W[j + 4];
}
压缩函数
// CF
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++)
{
SS1 = ROTL(
ROTL(A, 12)
+ E
+ ROTL(T[j < 16 ? 0 : 1], j)
, 7);
SS2 = SS1 ^ ROTL(A, 12);
TT1 = FF(A, B, C, j) + D + SS2 + W1[j];
TT2 = GG(E, F, G, j) + H + SS1 + W[j];
D = C;
C = ROTL(B, 9);
B = A;
A = TT1;
H = G;
G = ROTL(F, 19);
F = E;
E = P0(TT2);
}
实现
https://github.com/C0deStarr/CryptoImp/tree/main/Hash/sha
- sm3.h
- sm3.c