SM3密码杂凑算法实现及说明

SM3密码杂凑算法说明:https://wenku.baidu.com/view/8d67d80178563c1ec5da50e2524de518964bd3b6.html?qq-pf-to=pcqq.c2c

术语与定义

1 比特串bit string

由0和1组成的二进制数字序列。

2 大端big-endian

数据在内存中的一种表示格式,规定左边为高有效位,右边为低有效位。数的高阶字节放在存储器的低地址,数的低阶字节放在存储器的高地址。

3 消息message

任意有限长度的比特串。本文本中消息作为杂凑算法的输入数据。

4 杂凑值hash value

杂凑算法作用于消息后输出的特定长度的比特串。本文本中的杂凑值长度为256比特。

5 字word

长度为32的比特串

符号

SM3密码杂凑算法实现及说明_第1张图片

SM3密码杂凑算法实现及说明_第2张图片

常量与函数

1

2
SM3密码杂凑算法实现及说明_第3张图片

3
SM3密码杂凑算法实现及说明_第4张图片

4
SM3密码杂凑算法实现及说明_第5张图片

算法描述

概述

对长度为l(l < 2^64) 比特的消息m, SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度
为256比特

填充

假设消息m 的长度为l 比特。首先将比特“ 1”添加到消息的末尾,再添加k 个“ 0”, k是满
足l + 1 + k ≡ 448mod512 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度l的二进
制表示。填充后的消息m′ 的比特长度为512的倍数。

SM3密码杂凑算法实现及说明_第6张图片

迭代压缩

1 迭代过程

SM3密码杂凑算法实现及说明_第7张图片

2 消息扩展

SM3密码杂凑算法实现及说明_第8张图片

3 压缩函数

SM3密码杂凑算法实现及说明_第9张图片

压缩函数框图

SM3密码杂凑算法实现及说明_第10张图片

其中,字的存储为大端(big-endian)格式

4 杂凑值



SM3算法C实现

sm3.h

/*
* sm3.h
*
* 为使此算法兼容32位、64位下Linux或Windows系统,
* 选择 int 来表示 32 位整数。
* 消息长度最大限定为 2**32 - 1(单位:比特),
* 且为 8 的倍数(消息的最小单元为字节)。
*/
#ifndef _SM3_H_
#define _SM3_H_

/*
* SM3算法产生的哈希值大小(单位:字节)
*/
#define SM3_HASH_SIZE 32 

/*
* SM3上下文
*/
typedef struct SM3Context
{
	unsigned int intermediateHash[SM3_HASH_SIZE / 4];
	unsigned char messageBlock[64];
} SM3Context;

/*
* SM3计算函数
*/
unsigned char *SM3Calc(const unsigned char *message,
	unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);

#endif // _SM3_H_


sm3.c
/*
* sm3.c
*/
#include 
#include 
#include "sm3.h"

/*
* 判断运行环境是否为小端
*/
static const int endianTest = 1;
#define IsLittleEndian() (*(char *)&endianTest == 1)

/*
* 向左循环移位
*/
#define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) )

/*
* 反转四字节整型字节序
*/
unsigned int *ReverseWord(unsigned int *word)
{
	unsigned char *byte, temp;

	byte = (unsigned char *)word;
	temp = byte[0];
	byte[0] = byte[3];
	byte[3] = temp;

	temp = byte[1];
	byte[1] = byte[2];
	byte[2] = temp;
	return word;
}

/*
* T
*/
unsigned int T(int i)
{
	if (i >= 0 && i <= 15)
		return 0x79CC4519;
	else if (i >= 16 && i <= 63)
		return 0x7A879D8A;
	else
		return 0;
}

/*
* FF
*/
unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
	if (i >= 0 && i <= 15)
		return X ^ Y ^ Z;
	else if (i >= 16 && i <= 63)
		return (X & Y) | (X & Z) | (Y & Z);
	else
		return 0;
}

/*
* GG
*/
unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
	if (i >= 0 && i <= 15)
		return X ^ Y ^ Z;
	else if (i >= 16 && i <= 63)
		return (X & Y) | (~X & Z);
	else
		return 0;
}

/*
* P0
*/
unsigned int P0(unsigned int X)
{
	return X ^ LeftRotate(X, 9) ^ LeftRotate(X, 17);
}

/*
* P1
*/
unsigned int P1(unsigned int X)
{
	return X ^ LeftRotate(X, 15) ^ LeftRotate(X, 23);
}

/*
* 初始化函数
*/
void SM3Init(SM3Context *context)
{
	context->intermediateHash[0] = 0x7380166F;
	context->intermediateHash[1] = 0x4914B2B9;
	context->intermediateHash[2] = 0x172442D7;
	context->intermediateHash[3] = 0xDA8A0600;
	context->intermediateHash[4] = 0xA96F30BC;
	context->intermediateHash[5] = 0x163138AA;
	context->intermediateHash[6] = 0xE38DEE4D;
	context->intermediateHash[7] = 0xB0FB0E4E;
}

/*
* 处理消息块
*/
void SM3ProcessMessageBlock(SM3Context *context)
{
	int i;
	unsigned int W[68];
	unsigned int W_[64];
	unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2;

	/* 消息扩展 */
	for (i = 0; i < 16; i++)
	{
		W[i] = *(unsigned int *)(context->messageBlock + i * 4);
		if (IsLittleEndian())
			ReverseWord(W + i);
		//printf("%d: %x\n", i, W[i]);    
	}
	for (i = 16; i < 68; i++)
	{
		W[i] = P1(W[i - 16] ^ W[i - 9] ^ LeftRotate(W[i - 3], 15))
			^ LeftRotate(W[i - 13], 7)
			^ W[i - 6];
		//printf("%d: %x\n", i, W[i]);    
	}
	for (i = 0; i < 64; i++)
	{
		W_[i] = W[i] ^ W[i + 4];
		//printf("%d: %x\n", i, W_[i]);    
	}

	/* 消息压缩 */
	A = context->intermediateHash[0];
	B = context->intermediateHash[1];
	C = context->intermediateHash[2];
	D = context->intermediateHash[3];
	E = context->intermediateHash[4];
	F = context->intermediateHash[5];
	G = context->intermediateHash[6];
	H = context->intermediateHash[7];
	for (i = 0; i < 64; i++)
	{
		SS1 = LeftRotate((LeftRotate(A, 12) + E + LeftRotate(T(i), i)), 7);
		SS2 = SS1 ^ LeftRotate(A, 12);
		TT1 = FF(A, B, C, i) + D + SS2 + W_[i];
		TT2 = GG(E, F, G, i) + H + SS1 + W[i];
		D = C;
		C = LeftRotate(B, 9);
		B = A;
		A = TT1;
		H = G;
		G = LeftRotate(F, 19);
		F = E;
		E = P0(TT2);
	}
	context->intermediateHash[0] ^= A;
	context->intermediateHash[1] ^= B;
	context->intermediateHash[2] ^= C;
	context->intermediateHash[3] ^= D;
	context->intermediateHash[4] ^= E;
	context->intermediateHash[5] ^= F;
	context->intermediateHash[6] ^= G;
	context->intermediateHash[7] ^= H;
}

/*
* SM3算法主函数
*/
unsigned char *SM3Calc(const unsigned char *message,
	unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE])
{
	SM3Context context;
	unsigned int i, remainder, bitLen;

	/* 初始化上下文 */
	SM3Init(&context);

	/* 对前面的消息分组进行处理 */
	for (i = 0; i < messageLen / 64; i++)
	{
		memcpy(context.messageBlock, message + i * 64, 64);
		SM3ProcessMessageBlock(&context);
	}

	/* 填充消息分组,并处理 */
	bitLen = messageLen * 8;
	if (IsLittleEndian())
		ReverseWord(&bitLen);
	remainder = messageLen % 64;
	memcpy(context.messageBlock, message + i * 64, remainder);
	context.messageBlock[remainder] = 0x80;
	if (remainder <= 55)
	{
		/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
		* 故将高 4 个字节赋为 0 。*/
		memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1 - 8 + 4);
		memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
		SM3ProcessMessageBlock(&context);
	}
	else
	{
		memset(context.messageBlock + remainder + 1, 0, 64 - remainder - 1);
		SM3ProcessMessageBlock(&context);
		/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
		* 故将高 4 个字节赋为 0 。*/
		memset(context.messageBlock, 0, 64 - 4);
		memcpy(context.messageBlock + 64 - 4, &bitLen, 4);
		SM3ProcessMessageBlock(&context);
	}

	/* 返回结果 */
	if (IsLittleEndian())
	for (i = 0; i < 8; i++)
		ReverseWord(context.intermediateHash + i);
	memcpy(digest, context.intermediateHash, SM3_HASH_SIZE);

	return digest;
}
sm3test.c
#include 
#include 
#include "sm3.h"
#include 

//#pragma comment(lib,"sm3dll2")
//extern "C" void SM3Call(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);

int main( int argc, char *argv[] )
{
	unsigned char input[256] = "abc";
	int ilen = 3;
	unsigned char output[32];
	int i;
	// ctx;

	printf("Message:\n");
	printf("%s\n",input);

	SM3Calc(input, ilen, output);
	printf("Hash:\n   ");
	for(i=0; i<32; i++)
	{
		printf("%02x",output[i]);
		if (((i+1) % 4 ) == 0) printf(" ");
	} 

	printf("\n");


	unsigned char input2[256] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
	int ilen2 = 64;
	unsigned char output2[32];
	int i2;
	// ctx;

	printf("Message:\n");
	printf("%s\n", input2);

	SM3Calc(input2, ilen2, output2);
	printf("Hash:\n   ");
	for (i2 = 0; i2<32; i2++)
	{
		printf("%02x", output2[i2]);
		if (((i2 + 1) % 4) == 0) printf(" ");
	}
	printf("\n");
	system("pause");
}


你可能感兴趣的:(SM3密码杂凑算法实现及说明)