SM3是国产哈希算法,在商用密码体系中,主要用于数字签名及验证、消息认证码生成及验证、随机数生成等。对于用户需要加密的数据在加密后会生成一个固定长度(32字节)的哈希值。SM3算法是公开的。实现原理如下图所示:

C代码展示:

完整代码见github:https://github.com/CMwshuai/Algorithm.git

1、初始值IV

static const unsigned int IV[8] =
{
	0x7380166F,	0x4914B2B9,
	0x172442D7,	0xDA8A0600,
	0xA96F30BC,	0x163138AA,
	0xE38DEE4D,	0xB0FB0E4E,
};

2、常量初始化T

static void _init_T()
{
	int i = 0;
	for (; i < 16; i++)
		T[i] = 0x79CC4519;
	for (; i < 64; i++)
		T[i] = 0x7A879D8A;
}

3、 布尔函数_FF,_GG

static unsigned int _FF(
            const unsigned int X,
            const unsigned int Y,
            const unsigned int Z,
            const unsigned int j)
{
	if (0 <= j && j < 16)
		return (X ^ Y ^ Z);
	else if (16 <= j && j < 64)
		return ((X & Y) | (X & Z) | (Y & Z));

	return 0;
}

static unsigned int _GG(
        const unsigned int X, 
        const unsigned int Y, 
        const unsigned int Z, 
        const unsigned int j)
{
	if (0 <= j && j < 16)
		return (X ^ Y ^ Z);
	else if (16 <= j && j < 64)
		return ((X & Y) | ((~X) & Z));

	return 0;
}

4、置换函数_P0,_P1

static unsigned int _P0(const unsigned int X)
{
	return (X ^ (_rotate_left_move(X, 9)) ^ (_rotate_left_move(X, 17)));
}

static unsigned int _P1(const unsigned int X)
{
	return (X ^ (_rotate_left_move(X, 15)) ^ (_rotate_left_move(X, 23)));
}

 5、消息填充

unsigned int nGroupNum = (nSrcLen + 1 + 8 + 64) / 64;
unsigned char *ucpMsgBuf = (unsigned char*)malloc(nGroupNum * 64);
memset(ucpMsgBuf, 0, nGroupNum * 64);
memcpy(ucpMsgBuf, ucpSrcData, nSrcLen);
ucpMsgBuf[nSrcLen] = 0x80;

int i = 0;
for (i = 0; i < 8; i++)
{
	ucpMsgBuf[nGroupNum * 64 - i - 1] = ((unsigned long long)(nSrcLen * 8) >> (i * 8)) & 0xFF;
}

 6、迭代压缩

static unsigned int _CF(unsigned char* ucpSrcMsg, unsigned int nHash[8])
{
	unsigned int W68[68] = { 0 };
	unsigned int W64[64] = { 0 };

	//message extension
	int j = 0;
	for (j = 0; j < 16; j++)
	{
		W68[j] = ((unsigned int)ucpSrcMsg[j * 4 + 0] << 24) & 0xFF000000
			| ((unsigned int)ucpSrcMsg[j * 4 + 1] << 16) & 0x00FF0000
			| ((unsigned int)ucpSrcMsg[j * 4 + 2] << 8) & 0x0000FF00
			| ((unsigned int)ucpSrcMsg[j * 4 + 3] << 0) & 0x000000FF;
	}

	for (j = 16; j < 68; j++)
	{
		W68[j] = _P1(W68[j - 16] ^ W68[j - 9] ^ (_rotate_left_move(W68[j - 3], 15))) ^ (_rotate_left_move(W68[j - 13], 7)) ^ W68[j - 6];
	}

	for (j = 0; j < 64; j++)
	{
		W64[j] = W68[j] ^ W68[j + 4];
	}
	
	//iterative process
	unsigned int A_G[8] = { 0 };
	for (j = 0; j < 8; j++)
	{
		A_G[j] = nHash[j];
	}

	//tempporary variable
	unsigned int SS1 = 0, SS2 = 0, TT1 = 0, TT2 = 0;

	for (j = 0; j < 64; j++)
	{
		SS1 = _rotate_left_move((_rotate_left_move(A_G[A], 12) + A_G[E] + _rotate_left_move(T[j], j % 32)), 7);
		SS2 = SS1 ^ (_rotate_left_move(A_G[A], 12));
		TT1 = _FF(A_G[A], A_G[B], A_G[C], j) + A_G[D] + SS2 + W64[j];
		TT2 = _GG(A_G[E], A_G[F], A_G[G], j) + A_G[H] + SS1 + W68[j];
		A_G[D] = A_G[C];
		A_G[C] = _rotate_left_move(A_G[B], 9);
		A_G[B] = A_G[A];
		A_G[A] = TT1;
		A_G[H] = A_G[G];
		A_G[G] = _rotate_left_move(A_G[F], 19);
		A_G[F] = A_G[E];
		A_G[E] = _P0(TT2);
	}

	for (j = 0; j < 8; j++)
	{
		nHash[j] = A_G[j] ^ nHash[j];
	}

	return 0;
}

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐