/*
* 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 / ];
unsigned char messageBlock[];
} SM3Context; /*
* SM3计算函数
*/
unsigned char *SM3Calc(const unsigned char *message,
unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]); #endif // _SM3_H_
/*
* sm3.c
*/
#include <stdio.h>
#include <memory.h>
#include "sm3.h" /*
* 判断运行环境是否为小端
*/
static const int endianTest = ;
#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[];
byte[] = byte[];
byte[] = temp; temp = byte[];
byte[] = byte[];
byte[] = temp;
return word;
} /*
* T
*/
unsigned int T(int i)
{
if (i >= && i <= )
return 0x79CC4519;
else if (i >= && i <= )
return 0x7A879D8A;
else
return ;
} /*
* FF
*/
unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
if (i >= && i <= )
return X ^ Y ^ Z;
else if (i >= && i <= )
return (X & Y) | (X & Z) | (Y & Z);
else
return ;
} /*
* GG
*/
unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i)
{
if (i >= && i <= )
return X ^ Y ^ Z;
else if (i >= && i <= )
return (X & Y) | (~X & Z);
else
return ;
} /*
* P0
*/
unsigned int P0(unsigned int X)
{
return X ^ LeftRotate(X, ) ^ LeftRotate(X, );
} /*
* P1
*/
unsigned int P1(unsigned int X)
{
return X ^ LeftRotate(X, ) ^ LeftRotate(X, );
} /*
* 初始化函数
*/
void SM3Init(SM3Context *context)
{
context->intermediateHash[] = 0x7380166F;
context->intermediateHash[] = 0x4914B2B9;
context->intermediateHash[] = 0x172442D7;
context->intermediateHash[] = 0xDA8A0600;
context->intermediateHash[] = 0xA96F30BC;
context->intermediateHash[] = 0x163138AA;
context->intermediateHash[] = 0xE38DEE4D;
context->intermediateHash[] = 0xB0FB0E4E;
} /*
* 处理消息块
*/
void SM3ProcessMessageBlock(SM3Context *context)
{
int i;
unsigned int W[];
unsigned int W_[];
unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2; /* 消息扩展 */
for (i = ; i < ; i++)
{
W[i] = *(unsigned int *)(context->messageBlock + i * );
if (IsLittleEndian())
ReverseWord(W + i);
//printf("%d: %x\n", i, W[i]);
}
for (i = ; i < ; i++)
{
W[i] = P1(W[i - ] ^ W[i - ] ^ LeftRotate(W[i - ], ))
^ LeftRotate(W[i - ], )
^ W[i - ];
//printf("%d: %x\n", i, W[i]);
}
for (i = ; i < ; i++)
{
W_[i] = W[i] ^ W[i + ];
//printf("%d: %x\n", i, W_[i]);
} /* 消息压缩 */
A = context->intermediateHash[];
B = context->intermediateHash[];
C = context->intermediateHash[];
D = context->intermediateHash[];
E = context->intermediateHash[];
F = context->intermediateHash[];
G = context->intermediateHash[];
H = context->intermediateHash[];
for (i = ; i < ; i++)
{
SS1 = LeftRotate((LeftRotate(A, ) + E + LeftRotate(T(i), i)), );
SS2 = SS1 ^ LeftRotate(A, );
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, );
B = A;
A = TT1;
H = G;
G = LeftRotate(F, );
F = E;
E = P0(TT2);
}
context->intermediateHash[] ^= A;
context->intermediateHash[] ^= B;
context->intermediateHash[] ^= C;
context->intermediateHash[] ^= D;
context->intermediateHash[] ^= E;
context->intermediateHash[] ^= F;
context->intermediateHash[] ^= G;
context->intermediateHash[] ^= 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 = ; i < messageLen / ; i++)
{
memcpy(context.messageBlock, message + i * , );
SM3ProcessMessageBlock(&context);
} /* 填充消息分组,并处理 */
bitLen = messageLen * ;
if (IsLittleEndian())
ReverseWord(&bitLen);
remainder = messageLen % ;
memcpy(context.messageBlock, message + i * , remainder);
context.messageBlock[remainder] = 0x80;
if (remainder <= )
{
/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
* 故将高 4 个字节赋为 0 。*/
memset(context.messageBlock + remainder + , , - remainder - - + );
memcpy(context.messageBlock + - , &bitLen, );
SM3ProcessMessageBlock(&context);
}
else
{
memset(context.messageBlock + remainder + , , - remainder - );
SM3ProcessMessageBlock(&context);
/* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
* 故将高 4 个字节赋为 0 。*/
memset(context.messageBlock, , - );
memcpy(context.messageBlock + - , &bitLen, );
SM3ProcessMessageBlock(&context);
} /* 返回结果 */
if (IsLittleEndian())
for (i = ; i < ; i++)
ReverseWord(context.intermediateHash + i);
memcpy(digest, context.intermediateHash, SM3_HASH_SIZE); return digest;
}
05-11 13:40