SM3算法 C语言 (从OpenSSL库中分离算法)
- 实现SM3算法,并打印 “填充后的消息 + 扩展后的消息 + 迭代压缩中间值 + Hash值”
- 参考:
- 代码链接:SM3算法-从OpenSSL库中分离算法 ← ← ←
- SM3国密在线工具:https://the-x.cn/zh-cn/hash/ShangMi3Algorithm.aspx
- 讲解视频:【SM3加密算法】|密码杂凑算法 | Hash算法 | 密码学 | 信息安全| 消息摘要
一、OpenSSL简介
OpenSSL 是用于传输层安全性 (TLS) 和安全套接字层 (SSL) 协议的一个强大、商业级和功能齐全的工具包,它也是一个通用的密码学库。包含有RSA、SM4、DES、AES等诸多加密算法。
OpenSSL GitHub地址如下:
GitHub - openssl/openssl: TLS/SSL and crypto library
在日常的开发工作中,有时只想用OpenSSL库中的一种算法,此时调用整个OpenSSL库,往往是没必要的;再或者在嵌入式平台使用某一算法,那我们只移植这个算法,没有必要移植整个OpenSSL库。
二、SM3简介
SM3是我国采用的一种密码散列函数标准,由国家密码管理局于2010年12月17日发布。相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。它可以将任意长度的消息压缩成固定长度的摘要,主要用于数字签名和数据完整性保护等
在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。
三、移植过程(Windows)
(一)下载代码
从OpenSSL的Github仓库下载代码,可以下载master分支,也可以下载最新的release版本。将下载的文件解压,得到代码。
重点关注红框目录:
- crypto目录内是各种加密算法
- include目录内是各加密算法对外接口的头文件
(二)准备环境
新建Visual Studio C++ 控制台项目"sm3test",编译选项是:x86\Debug
(三)准备文件
- 复制OpenSSL源码中:/crypto/sm3文件夹到VS工程代码目录下
- 复制OpenSSL源码中:/include/internal/sm3.h文件到VS工程代码目录中sm3文件夹内
- 复制OpenSSL源码中:/include/crypto/md32_common.h文件到VS工程代码目录中sm3文件夹内
- 复制完成后,VS工程代码目录sm3文件夹内文件如下:
删除目录内的如下本项目中无用文件:
- build.info
- legacy_sm3.c
(四)修改代码
1.修改调用文件
在VS工程中含有main函数的主文件:sm3test.cpp中,增加包含sm3.h头文件
#include "sm3/sm3.h"
在main函数中添加如下代码
SM3_CTX SMC;
ossl_sm3_init(&SMC);
const unsigned char Data[1024] = "abc";
unsigned char md[SM3_DIGEST_LENGTH] = { 0 };
printf("输入数据:%s\n", Data);
ossl_sm3_update(&SMC, Data, strlen((const char*)Data));
ossl_sm3_final(md, &SMC);
printf("Hash值:");
for (int i = 0; i < SM3_DIGEST_LENGTH; i++) {
printf("%02x", *(md + i));
if (i % 4 == 3) printf(" ");
}
修改后的sm3test.cpp代码如下:
#include <iostream>
#include "sm3/sm3.h"
int main()
{
SM3_CTX SMC;
ossl_sm3_init(&SMC);
const unsigned char Data[1024] = "abc";
unsigned char md[SM3_DIGEST_LENGTH] = { 0 };
printf("输入数据:%s\n", Data);
ossl_sm3_update(&SMC, Data, strlen((const char*)Data));
ossl_sm3_final(md, &SMC);
printf("Hash值:");
for (int i = 0; i < SM3_DIGEST_LENGTH; i++) {
printf("%02x", *(md + i));
if (i % 4 == 3) printf(" ");
}
}
2.修改sm3.h
删除条件编译 OPENSSL_SM3_H
删除头文件 # include <openssl/opensslconf.h>
删除条件编译 OPENSSL_NO_SM3
添加C++调用时的宏
修改或删除后的文件如下:
# pragma once
# ifdef __cplusplus
extern "C" {
# endif
# define SM3_DIGEST_LENGTH 32
# define SM3_WORD unsigned int
# define SM3_CBLOCK 64
# define SM3_LBLOCK (SM3_CBLOCK/4)
typedef struct SM3state_st {
SM3_WORD A, B, C, D, E, F, G, H;
SM3_WORD Nl, Nh;
SM3_WORD data[SM3_LBLOCK];
unsigned int num;
} SM3_CTX;
int ossl_sm3_init(SM3_CTX* c);
int ossl_sm3_update(SM3_CTX* c, const void* data, size_t len);
int ossl_sm3_final(unsigned char* md, SM3_CTX* c);
# ifdef __cplusplus
}
# endif
3.修改sm3_local.h
修改头文件# include "internal/sm3.h"
改为#include "sm3.h"
修改头文件# include "crypto/md32_common.h"
改为#include "md32_common.h"
修改或删除后的文件如下:
#include <string.h>
#include "sm3.h"
#define DATA_ORDER_IS_BIG_ENDIAN
#define HASH_LONG SM3_WORD
#define HASH_CTX SM3_CTX
#define HASH_CBLOCK SM3_CBLOCK
#define HASH_UPDATE ossl_sm3_update
#define HASH_TRANSFORM ossl_sm3_transform
#define HASH_FINAL ossl_sm3_final
#define HASH_MAKE_STRING(c, s) \
do { \
unsigned long ll; \
ll=(c)->A; (void)HOST_l2c(ll, (s)); \
ll=(c)->B; (void)HOST_l2c(ll, (s)); \
ll=(c)->C; (void)HOST_l2c(ll, (s)); \
ll=(c)->D; (void)HOST_l2c(ll, (s)); \
ll=(c)->E; (void)HOST_l2c(ll, (s)); \
ll=(c)->F; (void)HOST_l2c(ll, (s)); \
ll=(c)->G; (void)HOST_l2c(ll, (s)); \
ll=(c)->H; (void)HOST_l2c(ll, (s)); \
} while (0)
#define HASH_BLOCK_DATA_ORDER ossl_sm3_block_data_order
void ossl_sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
void ossl_sm3_transform(SM3_CTX *c, const unsigned char *data);
#include "md32_common.h"
#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17))
#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23))
#define FF0(X,Y,Z) (X ^ Y ^ Z)
#define GG0(X,Y,Z) (X ^ Y ^ Z)
#define FF1(X,Y,Z) ((X & Y) | ((X | Y) & Z))
#define GG1(X,Y,Z) ((Z ^ (X & (Y ^ Z))))
#define EXPAND(W0,W7,W13,W3,W10) \
(P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10)
#define RND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG) \
do { \
const SM3_WORD A12 = ROTATE(A, 12); \
const SM3_WORD A12_SM = A12 + E + TJ; \
const SM3_WORD SS1 = ROTATE(A12_SM, 7); \
const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj); \
const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi; \
B = ROTATE(B, 9); \
D = TT1; \
F = ROTATE(F, 19); \
H = P0(TT2); \
} while(0)
#define R1(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF0,GG0)
#define R2(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF1,GG1)
#define SM3_A 0x7380166fUL
#define SM3_B 0x4914b2b9UL
#define SM3_C 0x172442d7UL
#define SM3_D 0xda8a0600UL
#define SM3_E 0xa96f30bcUL
#define SM3_F 0x163138aaUL
#define SM3_G 0xe38dee4dUL
#define SM3_H 0xb0fb0e4eUL
4.修改sm3.c
删除头文件#include <openssl/e_os2.h>
修改或删除后的文件如下:
#include "sm3_local.h"
int ossl_sm3_init(SM3_CTX *c)
{
memset(c, 0, sizeof(*c));
c->A = SM3_A;
c->B = SM3_B;
c->C = SM3_C;
c->D = SM3_D;
c->E = SM3_E;
c->F = SM3_F;
c->G = SM3_G;
c->H = SM3_H;
return 1;
}
void ossl_sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num)
{
const unsigned char *data = p;
register unsigned MD32_REG_T A, B, C, D, E, F, G, H;
unsigned MD32_REG_T W00, W01, W02, W03, W04, W05, W06, W07,
W08, W09, W10, W11, W12, W13, W14, W15;
for (; num--;) {
A = ctx->A;
B = ctx->B;
C = ctx->C;
D = ctx->D;
E = ctx->E;
F = ctx->F;
G = ctx->G;
H = ctx->H;
/*
* We have to load all message bytes immediately since SM3 reads
* them slightly out of order.
*/
(void)HOST_c2l(data, W00);
(void)HOST_c2l(data, W01);
(void)HOST_c2l(data, W02);
(void)HOST_c2l(data, W03);
(void)HOST_c2l(data, W04);
(void)HOST_c2l(data, W05);
(void)HOST_c2l(data, W06);
(void)HOST_c2l(data, W07);
(void)HOST_c2l(data, W08);
(void)HOST_c2l(data, W09);
(void)HOST_c2l(data, W10);
(void)HOST_c2l(data, W11);
(void)HOST_c2l(data, W12);
(void)HOST_c2l(data, W13);
(void)HOST_c2l(data, W14);
(void)HOST_c2l(data, W15);
R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
ctx->A ^= A;
ctx->B ^= B;
ctx->C ^= C;
ctx->D ^= D;
ctx->E ^= E;
ctx->F ^= F;
ctx->G ^= G;
ctx->H ^= H;
}
}
5.修改md32_common.h
删除头文件# include <openssl/crypto.h>
删除代码中全部的OPENSSL_cleanse();
- 解释:经查阅openssl代码中的OPENSSL_cleanse函数声明,此函数作用等同与标准C中的memset(p,0,size)功能,是将参数一内存清0,本文件中调用该函数的地方,其参数1均为栈空间,函数结束后将自动回收,因此没必要手动清0,因此该函数可以不调用,若不放心,可以用memset函数替代。
修改或删除后的文件如下:
#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# error "DATA_ORDER must be defined!"
#endif
#ifndef HASH_CBLOCK
# error "HASH_CBLOCK must be defined!"
#endif
#ifndef HASH_LONG
# error "HASH_LONG must be defined!"
#endif
#ifndef HASH_CTX
# error "HASH_CTX must be defined!"
#endif
#ifndef HASH_UPDATE
# error "HASH_UPDATE must be defined!"
#endif
#ifndef HASH_TRANSFORM
# error "HASH_TRANSFORM must be defined!"
#endif
#ifndef HASH_FINAL
# error "HASH_FINAL must be defined!"
#endif
#ifndef HASH_BLOCK_DATA_ORDER
# error "HASH_BLOCK_DATA_ORDER must be defined!"
#endif
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++))) ) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff), \
l)
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
l)
#endif
/*
* Time for some action :-)
*/
int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
{
const unsigned char *data = data_;
unsigned char *p;
HASH_LONG l;
size_t n;
if (len == 0)
return 1;
l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
if (l < c->Nl) /* overflow */
c->Nh++;
c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
* 16-bit */
c->Nl = l;
n = c->num;
if (n != 0) {
p = (unsigned char *)c->data;
if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
memcpy(p + n, data, HASH_CBLOCK - n);
HASH_BLOCK_DATA_ORDER(c, p, 1);
n = HASH_CBLOCK - n;
data += n;
len -= n;
c->num = 0;
/*
* We use memset rather than OPENSSL_cleanse() here deliberately.
* Using OPENSSL_cleanse() here could be a performance issue. It
* will get properly cleansed on finalisation so this isn't a
* security problem.
*/
memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
} else {
memcpy(p + n, data, len);
c->num += (unsigned int)len;
return 1;
}
}
n = len / HASH_CBLOCK;
if (n > 0) {
HASH_BLOCK_DATA_ORDER(c, data, n);
n *= HASH_CBLOCK;
data += n;
len -= n;
}
if (len != 0) {
p = (unsigned char *)c->data;
c->num = (unsigned int)len;
memcpy(p, data, len);
}
return 1;
}
void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data)
{
HASH_BLOCK_DATA_ORDER(c, data, 1);
}
int HASH_FINAL(unsigned char *md, HASH_CTX *c)
{
unsigned char *p = (unsigned char *)c->data;
size_t n = c->num;
p[n] = 0x80; /* there is always room for one */
n++;
if (n > (HASH_CBLOCK - 8)) {
memset(p + n, 0, HASH_CBLOCK - n);
n = 0;
HASH_BLOCK_DATA_ORDER(c, p, 1);
}
memset(p + n, 0, HASH_CBLOCK - 8 - n);
p += HASH_CBLOCK - 8;
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
(void)HOST_l2c(c->Nh, p);
(void)HOST_l2c(c->Nl, p);
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
(void)HOST_l2c(c->Nl, p);
(void)HOST_l2c(c->Nh, p);
#endif
p -= HASH_CBLOCK;
HASH_BLOCK_DATA_ORDER(c, p, 1);
c->num = 0;
#ifndef HASH_MAKE_STRING
# error "HASH_MAKE_STRING must be defined!"
#else
HASH_MAKE_STRING(c, md);
#endif
return 1;
}
#ifndef MD32_REG_T
# if defined(__alpha) || defined(__sparcv9) || defined(__mips)
# define MD32_REG_T long
/*
* This comment was originally written for MD5, which is why it
* discusses A-D. But it basically applies to all 32-bit digests,
* which is why it was moved to common header file.
*
* In case you wonder why A-D are declared as long and not
* as MD5_LONG. Doing so results in slight performance
* boost on LP64 architectures. The catch is we don't
* really care if 32 MSBs of a 64-bit register get polluted
* with eventual overflows as we *save* only 32 LSBs in
* *either* case. Now declaring 'em long excuses the compiler
* from keeping 32 MSBs zeroed resulting in 13% performance
* improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
* Well, to be honest it should say that this *prevents*
* performance degradation.
*/
# else
/*
* Above is not absolute and there are LP64 compilers that
* generate better code if MD32_REG_T is defined int. The above
* pre-processor condition reflects the circumstances under which
* the conclusion was made and is subject to further extension.
*/
# define MD32_REG_T int
# endif
#endif
(五)编译运行
将sm3.h,sm3.c,sm3_local.h,md32_common.h文件,配置添加到VS工程中。
编译运行,输出sm3结果如下:
输入数据:abc
Hash值:66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
四、Ubuntu上运行(Linux)
(一)目录结构
(二)代码
1.sm3test.c
#include <stdio.h>
#include <string.h>
#include "include/sm3.h"
int main() {
SM3_CTX SMC;
ossl_sm3_init(&SMC);
unsigned char Data[1024];
unsigned char md[SM3_DIGEST_LENGTH] = { 0 };
printf("输入数据: \n");
scanf("%s",(char *)Data);
printf("十六进制:\n");
for (int i = 0; i < strlen((char*)Data); i++) {
printf("0x%02x ", *(Data+i));
if(i%8==7) printf("\n");
}
printf("\n");
ossl_sm3_update(&SMC, Data, strlen((char*)Data));
ossl_sm3_final(md, &SMC);
printf("\nHash值:\n");
for (int i = 0; i < SM3_DIGEST_LENGTH; i++) {
printf("%02x", *(md + i));
if (i % 4 == 3) {
printf(" ");
}
}
printf("\n");
return 0;
}
2.sm3.h
# pragma once
# ifdef __cplusplus
extern "C" {
# endif
# define SM3_DIGEST_LENGTH 32
# define SM3_WORD unsigned int
# define SM3_CBLOCK 64
# define SM3_LBLOCK (SM3_CBLOCK/4)
typedef struct SM3state_st {
SM3_WORD A, B, C, D, E, F, G, H;
SM3_WORD Nl, Nh;
SM3_WORD data[SM3_LBLOCK];
unsigned int num;
} SM3_CTX;
int ossl_sm3_init(SM3_CTX* c);
int ossl_sm3_update(SM3_CTX* c, const void* data, size_t len);
int ossl_sm3_final(unsigned char* md, SM3_CTX* c);
# ifdef __cplusplus
}
# endif
3.sm3_local.h
#include <string.h>
#include "sm3.h"
#define DATA_ORDER_IS_BIG_ENDIAN
#define HASH_LONG SM3_WORD
#define HASH_CTX SM3_CTX
#define HASH_CBLOCK SM3_CBLOCK
#define HASH_UPDATE ossl_sm3_update
#define HASH_TRANSFORM ossl_sm3_transform
#define HASH_FINAL ossl_sm3_final
#define HASH_MAKE_STRING(c, s) \
do { \
unsigned long ll; \
ll=(c)->A; (void)HOST_l2c(ll, (s)); \
ll=(c)->B; (void)HOST_l2c(ll, (s)); \
ll=(c)->C; (void)HOST_l2c(ll, (s)); \
ll=(c)->D; (void)HOST_l2c(ll, (s)); \
ll=(c)->E; (void)HOST_l2c(ll, (s)); \
ll=(c)->F; (void)HOST_l2c(ll, (s)); \
ll=(c)->G; (void)HOST_l2c(ll, (s)); \
ll=(c)->H; (void)HOST_l2c(ll, (s)); \
} while (0)
#define HASH_BLOCK_DATA_ORDER ossl_sm3_block_data_order
void ossl_sm3_block_data_order(SM3_CTX *c, const void *p, size_t num);
void ossl_sm3_transform(SM3_CTX *c, const unsigned char *data);
#include "md32_common.h"
#define P0(X) (X ^ ROTATE(X, 9) ^ ROTATE(X, 17))
#define P1(X) (X ^ ROTATE(X, 15) ^ ROTATE(X, 23))
#define FF0(X,Y,Z) (X ^ Y ^ Z)
#define GG0(X,Y,Z) (X ^ Y ^ Z)
#define FF1(X,Y,Z) ((X & Y) | ((X | Y) & Z))
#define GG1(X,Y,Z) ((Z ^ (X & (Y ^ Z))))
#define EXPAND(W0,W7,W13,W3,W10) \
(P1(W0 ^ W7 ^ ROTATE(W13, 15)) ^ ROTATE(W3, 7) ^ W10)
#define RND(A, B, C, D, E, F, G, H, TJ, Wi, Wj, FF, GG) \
do { \
const SM3_WORD A12 = ROTATE(A, 12); \
const SM3_WORD A12_SM = A12 + E + TJ; \
const SM3_WORD SS1 = ROTATE(A12_SM, 7); \
const SM3_WORD TT1 = FF(A, B, C) + D + (SS1 ^ A12) + (Wj); \
const SM3_WORD TT2 = GG(E, F, G) + H + SS1 + Wi; \
B = ROTATE(B, 9); \
D = TT1; \
F = ROTATE(F, 19); \
H = P0(TT2); \
} while(0)
#define R1(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF0,GG0)
#define R2(A,B,C,D,E,F,G,H,TJ,Wi,Wj) \
RND(A,B,C,D,E,F,G,H,TJ,Wi,Wj,FF1,GG1)
#define SM3_A 0x7380166fUL
#define SM3_B 0x4914b2b9UL
#define SM3_C 0x172442d7UL
#define SM3_D 0xda8a0600UL
#define SM3_E 0xa96f30bcUL
#define SM3_F 0x163138aaUL
#define SM3_G 0xe38dee4dUL
#define SM3_H 0xb0fb0e4eUL
4.sm3.c
#include "sm3_local.h"
int ossl_sm3_init(SM3_CTX *c) {
memset(c, 0, sizeof(*c));
c->A = SM3_A;
c->B = SM3_B;
c->C = SM3_C;
c->D = SM3_D;
c->E = SM3_E;
c->F = SM3_F;
c->G = SM3_G;
c->H = SM3_H;
return 1;
}
void ossl_sm3_block_data_order(SM3_CTX *ctx, const void *p, size_t num) {
const unsigned char *data = p;
register unsigned MD32_REG_T A, B, C, D, E, F, G, H;
unsigned MD32_REG_T A1[65],B1[65],C1[65],D1[65],E1[65],F1[65],G1[65],H1[65];
unsigned MD32_REG_T W00, W01, W02, W03, W04, W05, W06, W07, W08, W09, W10, W11, W12, W13, W14, W15;
unsigned MD32_REG_T W[68];
int i;
for (; num--;) {
A = ctx->A;
B = ctx->B;
C = ctx->C;
D = ctx->D;
E = ctx->E;
F = ctx->F;
G = ctx->G;
H = ctx->H;
/*
* We have to load all message bytes immediately since SM3 reads
* them slightly out of order.
*/
(void)HOST_c2l(data, W00);
(void)HOST_c2l(data, W01);
(void)HOST_c2l(data, W02);
(void)HOST_c2l(data, W03);
(void)HOST_c2l(data, W04);
(void)HOST_c2l(data, W05);
(void)HOST_c2l(data, W06);
(void)HOST_c2l(data, W07);
(void)HOST_c2l(data, W08);
(void)HOST_c2l(data, W09);
(void)HOST_c2l(data, W10);
(void)HOST_c2l(data, W11);
(void)HOST_c2l(data, W12);
(void)HOST_c2l(data, W13);
(void)HOST_c2l(data, W14);
(void)HOST_c2l(data, W15);
W[0]=W00;
W[1]=W01;
W[2]=W02;
W[3]=W03;
W[4]=W04;
W[5]=W05;
W[6]=W06;
W[7]=W07;
W[8]=W08;
W[9]=W09;
W[10]=W10;
W[11]=W11;
W[12]=W12;
W[13]=W13;
W[14]=W14;
W[15]=W15;
printf("\n填充后的消息:\n");
for(i=0; i<16; i++) {
printf("%08x ",W[i]);
if(i%8==7) printf("\n");
}
A1[0]=A;
B1[0]=B;
C1[0]=C;
D1[0]=D;
E1[0]=E;
F1[0]=F;
G1[0]=G;
H1[0]=H;
R1(A, B, C, D, E, F, G, H, 0x79CC4519, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
A1[1]=D;
B1[1]=A;
C1[1]=B;
D1[1]=C;
E1[1]=H;
F1[1]=E;
G1[1]=F;
H1[1]=G;
R1(D, A, B, C, H, E, F, G, 0xF3988A32, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
A1[2]=C;
B1[2]=D;
C1[2]=A;
D1[2]=B;
E1[2]=G;
F1[2]=H;
G1[2]=E;
H1[2]=F;
R1(C, D, A, B, G, H, E, F, 0xE7311465, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
A1[3]=B;
B1[3]=C;
C1[3]=D;
D1[3]=A;
E1[3]=F;
F1[3]=G;
G1[3]=H;
H1[3]=E;
R1(B, C, D, A, F, G, H, E, 0xCE6228CB, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
A1[4]=A;
B1[4]=B;
C1[4]=C;
D1[4]=D;
E1[4]=E;
F1[4]=F;
G1[4]=G;
H1[4]=H;
R1(A, B, C, D, E, F, G, H, 0x9CC45197, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
A1[5]=D;
B1[5]=A;
C1[5]=B;
D1[5]=C;
E1[5]=H;
F1[5]=E;
G1[5]=F;
H1[5]=G;
R1(D, A, B, C, H, E, F, G, 0x3988A32F, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
A1[6]=C;
B1[6]=D;
C1[6]=A;
D1[6]=B;
E1[6]=G;
F1[6]=H;
G1[6]=E;
H1[6]=F;
R1(C, D, A, B, G, H, E, F, 0x7311465E, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
A1[7]=B;
B1[7]=C;
C1[7]=D;
D1[7]=A;
E1[7]=F;
F1[7]=G;
G1[7]=H;
H1[7]=E;
R1(B, C, D, A, F, G, H, E, 0xE6228CBC, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
A1[8]=A;
B1[8]=B;
C1[8]=C;
D1[8]=D;
E1[8]=E;
F1[8]=F;
G1[8]=G;
H1[8]=H;
R1(A, B, C, D, E, F, G, H, 0xCC451979, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
A1[9]=D;
B1[9]=A;
C1[9]=B;
D1[9]=C;
E1[9]=H;
F1[9]=E;
G1[9]=F;
H1[9]=G;
R1(D, A, B, C, H, E, F, G, 0x988A32F3, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
A1[10]=C;
B1[10]=D;
C1[10]=A;
D1[10]=B;
E1[10]=G;
F1[10]=H;
G1[10]=E;
H1[10]=F;
R1(C, D, A, B, G, H, E, F, 0x311465E7, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
A1[11]=B;
B1[11]=C;
C1[11]=D;
D1[11]=A;
E1[11]=F;
F1[11]=G;
G1[11]=H;
H1[11]=E;
R1(B, C, D, A, F, G, H, E, 0x6228CBCE, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
A1[12]=A;
B1[12]=B;
C1[12]=C;
D1[12]=D;
E1[12]=E;
F1[12]=F;
G1[12]=G;
H1[12]=H;
R1(A, B, C, D, E, F, G, H, 0xC451979C, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
A1[13]=D;
B1[13]=A;
C1[13]=B;
D1[13]=C;
E1[13]=H;
F1[13]=E;
G1[13]=F;
H1[13]=G;
R1(D, A, B, C, H, E, F, G, 0x88A32F39, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
A1[14]=C;
B1[14]=D;
C1[14]=A;
D1[14]=B;
E1[14]=G;
F1[14]=H;
G1[14]=E;
H1[14]=F;
R1(C, D, A, B, G, H, E, F, 0x11465E73, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
A1[15]=B;
B1[15]=C;
C1[15]=D;
D1[15]=A;
E1[15]=F;
F1[15]=G;
G1[15]=H;
H1[15]=E;
R1(B, C, D, A, F, G, H, E, 0x228CBCE6, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
W[16]=W00;
W[17]=W01;
W[18]=W02;
W[19]=W03;
W[20]=W04;
W[21]=W05;
W[22]=W06;
W[23]=W07;
W[24]=W08;
W[25]=W09;
W[26]=W10;
W[27]=W11;
W[28]=W12;
W[29]=W13;
W[30]=W14;
W[31]=W15;
A1[16]=A;
B1[16]=B;
C1[16]=C;
D1[16]=D;
E1[16]=E;
F1[16]=F;
G1[16]=G;
H1[16]=H;
R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
A1[17]=D;
B1[17]=A;
C1[17]=B;
D1[17]=C;
E1[17]=H;
F1[17]=E;
G1[17]=F;
H1[17]=G;
R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
A1[18]=C;
B1[18]=D;
C1[18]=A;
D1[18]=B;
E1[18]=G;
F1[18]=H;
G1[18]=E;
H1[18]=F;
R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
A1[19]=B;
B1[19]=C;
C1[19]=D;
D1[19]=A;
E1[19]=F;
F1[19]=G;
G1[19]=H;
H1[19]=E;
R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
A1[20]=A;
B1[20]=B;
C1[20]=C;
D1[20]=D;
E1[20]=E;
F1[20]=F;
G1[20]=G;
H1[20]=H;
R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
A1[21]=D;
B1[21]=A;
C1[21]=B;
D1[21]=C;
E1[21]=H;
F1[21]=E;
G1[21]=F;
H1[21]=G;
R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
A1[22]=C;
B1[22]=D;
C1[22]=A;
D1[22]=B;
E1[22]=G;
F1[22]=H;
G1[22]=E;
H1[22]=F;
R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
A1[23]=B;
B1[23]=C;
C1[23]=D;
D1[23]=A;
E1[23]=F;
F1[23]=G;
G1[23]=H;
H1[23]=E;
R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
A1[24]=A;
B1[24]=B;
C1[24]=C;
D1[24]=D;
E1[24]=E;
F1[24]=F;
G1[24]=G;
H1[24]=H;
R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
A1[25]=D;
B1[25]=A;
C1[25]=B;
D1[25]=C;
E1[25]=H;
F1[25]=E;
G1[25]=F;
H1[25]=G;
R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
A1[26]=C;
B1[26]=D;
C1[26]=A;
D1[26]=B;
E1[26]=G;
F1[26]=H;
G1[26]=E;
H1[26]=F;
R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
A1[27]=B;
B1[27]=C;
C1[27]=D;
D1[27]=A;
E1[27]=F;
F1[27]=G;
G1[27]=H;
H1[27]=E;
R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
A1[28]=A;
B1[28]=B;
C1[28]=C;
D1[28]=D;
E1[28]=E;
F1[28]=F;
G1[28]=G;
H1[28]=H;
R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
A1[29]=D;
B1[29]=A;
C1[29]=B;
D1[29]=C;
E1[29]=H;
F1[29]=E;
G1[29]=F;
H1[29]=G;
R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
A1[30]=C;
B1[30]=D;
C1[30]=A;
D1[30]=B;
E1[30]=G;
F1[30]=H;
G1[30]=E;
H1[30]=F;
R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
A1[31]=B;
B1[31]=C;
C1[31]=D;
D1[31]=A;
E1[31]=F;
F1[31]=G;
G1[31]=H;
H1[31]=E;
R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
W[32]=W00;
W[33]=W01;
W[34]=W02;
W[35]=W03;
W[36]=W04;
W[37]=W05;
W[38]=W06;
W[39]=W07;
W[40]=W08;
W[41]=W09;
W[42]=W10;
W[43]=W11;
W[44]=W12;
W[45]=W13;
W[46]=W14;
W[47]=W15;
A1[32]=A;
B1[32]=B;
C1[32]=C;
D1[32]=D;
E1[32]=E;
F1[32]=F;
G1[32]=G;
H1[32]=H;
R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
A1[33]=D;
B1[33]=A;
C1[33]=B;
D1[33]=C;
E1[33]=H;
F1[33]=E;
G1[33]=F;
H1[33]=G;
R2(D, A, B, C, H, E, F, G, 0xF50F3B14, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
A1[34]=C;
B1[34]=D;
C1[34]=A;
D1[34]=B;
E1[34]=G;
F1[34]=H;
G1[34]=E;
H1[34]=F;
R2(C, D, A, B, G, H, E, F, 0xEA1E7629, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
A1[35]=B;
B1[35]=C;
C1[35]=D;
D1[35]=A;
E1[35]=F;
F1[35]=G;
G1[35]=H;
H1[35]=E;
R2(B, C, D, A, F, G, H, E, 0xD43CEC53, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
A1[36]=A;
B1[36]=B;
C1[36]=C;
D1[36]=D;
E1[36]=E;
F1[36]=F;
G1[36]=G;
H1[36]=H;
R2(A, B, C, D, E, F, G, H, 0xA879D8A7, W04, W04 ^ W08);
W04 = EXPAND(W04, W11, W01, W07, W14);
A1[37]=D;
B1[37]=A;
C1[37]=B;
D1[37]=C;
E1[37]=H;
F1[37]=E;
G1[37]=F;
H1[37]=G;
R2(D, A, B, C, H, E, F, G, 0x50F3B14F, W05, W05 ^ W09);
W05 = EXPAND(W05, W12, W02, W08, W15);
A1[38]=C;
B1[38]=D;
C1[38]=A;
D1[38]=B;
E1[38]=G;
F1[38]=H;
G1[38]=E;
H1[38]=F;
R2(C, D, A, B, G, H, E, F, 0xA1E7629E, W06, W06 ^ W10);
W06 = EXPAND(W06, W13, W03, W09, W00);
A1[39]=B;
B1[39]=C;
C1[39]=D;
D1[39]=A;
E1[39]=F;
F1[39]=G;
G1[39]=H;
H1[39]=E;
R2(B, C, D, A, F, G, H, E, 0x43CEC53D, W07, W07 ^ W11);
W07 = EXPAND(W07, W14, W04, W10, W01);
A1[40]=A;
B1[40]=B;
C1[40]=C;
D1[40]=D;
E1[40]=E;
F1[40]=F;
G1[40]=G;
H1[40]=H;
R2(A, B, C, D, E, F, G, H, 0x879D8A7A, W08, W08 ^ W12);
W08 = EXPAND(W08, W15, W05, W11, W02);
A1[41]=D;
B1[41]=A;
C1[41]=B;
D1[41]=C;
E1[41]=H;
F1[41]=E;
G1[41]=F;
H1[41]=G;
R2(D, A, B, C, H, E, F, G, 0x0F3B14F5, W09, W09 ^ W13);
W09 = EXPAND(W09, W00, W06, W12, W03);
A1[42]=C;
B1[42]=D;
C1[42]=A;
D1[42]=B;
E1[42]=G;
F1[42]=H;
G1[42]=E;
H1[42]=F;
R2(C, D, A, B, G, H, E, F, 0x1E7629EA, W10, W10 ^ W14);
W10 = EXPAND(W10, W01, W07, W13, W04);
A1[43]=B;
B1[43]=C;
C1[43]=D;
D1[43]=A;
E1[43]=F;
F1[43]=G;
G1[43]=H;
H1[43]=E;
R2(B, C, D, A, F, G, H, E, 0x3CEC53D4, W11, W11 ^ W15);
W11 = EXPAND(W11, W02, W08, W14, W05);
A1[44]=A;
B1[44]=B;
C1[44]=C;
D1[44]=D;
E1[44]=E;
F1[44]=F;
G1[44]=G;
H1[44]=H;
R2(A, B, C, D, E, F, G, H, 0x79D8A7A8, W12, W12 ^ W00);
W12 = EXPAND(W12, W03, W09, W15, W06);
A1[45]=D;
B1[45]=A;
C1[45]=B;
D1[45]=C;
E1[45]=H;
F1[45]=E;
G1[45]=F;
H1[45]=G;
R2(D, A, B, C, H, E, F, G, 0xF3B14F50, W13, W13 ^ W01);
W13 = EXPAND(W13, W04, W10, W00, W07);
A1[46]=C;
B1[46]=D;
C1[46]=A;
D1[46]=B;
E1[46]=G;
F1[46]=H;
G1[46]=E;
H1[46]=F;
R2(C, D, A, B, G, H, E, F, 0xE7629EA1, W14, W14 ^ W02);
W14 = EXPAND(W14, W05, W11, W01, W08);
A1[47]=B;
B1[47]=C;
C1[47]=D;
D1[47]=A;
E1[47]=F;
F1[47]=G;
G1[47]=H;
H1[47]=E;
R2(B, C, D, A, F, G, H, E, 0xCEC53D43, W15, W15 ^ W03);
W15 = EXPAND(W15, W06, W12, W02, W09);
W[48]=W00;
W[49]=W01;
W[50]=W02;
W[51]=W03;
W[52]=W04;
W[53]=W05;
W[54]=W06;
W[55]=W07;
W[56]=W08;
W[57]=W09;
W[58]=W10;
W[59]=W11;
W[60]=W12;
W[61]=W13;
W[62]=W14;
W[63]=W15;
A1[48]=A;
B1[48]=B;
C1[48]=C;
D1[48]=D;
E1[48]=E;
F1[48]=F;
G1[48]=G;
H1[48]=H;
R2(A, B, C, D, E, F, G, H, 0x9D8A7A87, W00, W00 ^ W04);
W00 = EXPAND(W00, W07, W13, W03, W10);
A1[49]=D;
B1[49]=A;
C1[49]=B;
D1[49]=C;
E1[49]=H;
F1[49]=E;
G1[49]=F;
H1[49]=G;
R2(D, A, B, C, H, E, F, G, 0x3B14F50F, W01, W01 ^ W05);
W01 = EXPAND(W01, W08, W14, W04, W11);
A1[50]=C;
B1[50]=D;
C1[50]=A;
D1[50]=B;
E1[50]=G;
F1[50]=H;
G1[50]=E;
H1[50]=F;
R2(C, D, A, B, G, H, E, F, 0x7629EA1E, W02, W02 ^ W06);
W02 = EXPAND(W02, W09, W15, W05, W12);
A1[51]=B;
B1[51]=C;
C1[51]=D;
D1[51]=A;
E1[51]=F;
F1[51]=G;
G1[51]=H;
H1[51]=E;
R2(B, C, D, A, F, G, H, E, 0xEC53D43C, W03, W03 ^ W07);
W03 = EXPAND(W03, W10, W00, W06, W13);
W[64]=W00;
W[65]=W01;
W[66]=W02;
W[67]=W03;
A1[52]=A;
B1[52]=B;
C1[52]=C;
D1[52]=D;
E1[52]=E;
F1[52]=F;
G1[52]=G;
H1[52]=H;
R2(A, B, C, D, E, F, G, H, 0xD8A7A879, W04, W04 ^ W08);
A1[53]=D;
B1[53]=A;
C1[53]=B;
D1[53]=C;
E1[53]=H;
F1[53]=E;
G1[53]=F;
H1[53]=G;
R2(D, A, B, C, H, E, F, G, 0xB14F50F3, W05, W05 ^ W09);
A1[54]=C;
B1[54]=D;
C1[54]=A;
D1[54]=B;
E1[54]=G;
F1[54]=H;
G1[54]=E;
H1[54]=F;
R2(C, D, A, B, G, H, E, F, 0x629EA1E7, W06, W06 ^ W10);
A1[55]=B;
B1[55]=C;
C1[55]=D;
D1[55]=A;
E1[55]=F;
F1[55]=G;
G1[55]=H;
H1[55]=E;
R2(B, C, D, A, F, G, H, E, 0xC53D43CE, W07, W07 ^ W11);
A1[56]=A;
B1[56]=B;
C1[56]=C;
D1[56]=D;
E1[56]=E;
F1[56]=F;
G1[56]=G;
H1[56]=H;
R2(A, B, C, D, E, F, G, H, 0x8A7A879D, W08, W08 ^ W12);
A1[57]=D;
B1[57]=A;
C1[57]=B;
D1[57]=C;
E1[57]=H;
F1[57]=E;
G1[57]=F;
H1[57]=G;
R2(D, A, B, C, H, E, F, G, 0x14F50F3B, W09, W09 ^ W13);
A1[58]=C;
B1[58]=D;
C1[58]=A;
D1[58]=B;
E1[58]=G;
F1[58]=H;
G1[58]=E;
H1[58]=F;
R2(C, D, A, B, G, H, E, F, 0x29EA1E76, W10, W10 ^ W14);
A1[59]=B;
B1[59]=C;
C1[59]=D;
D1[59]=A;
E1[59]=F;
F1[59]=G;
G1[59]=H;
H1[59]=E;
R2(B, C, D, A, F, G, H, E, 0x53D43CEC, W11, W11 ^ W15);
A1[60]=A;
B1[60]=B;
C1[60]=C;
D1[60]=D;
E1[60]=E;
F1[60]=F;
G1[60]=G;
H1[60]=H;
R2(A, B, C, D, E, F, G, H, 0xA7A879D8, W12, W12 ^ W00);
A1[61]=D;
B1[61]=A;
C1[61]=B;
D1[61]=C;
E1[61]=H;
F1[61]=E;
G1[61]=F;
H1[61]=G;
R2(D, A, B, C, H, E, F, G, 0x4F50F3B1, W13, W13 ^ W01);
A1[62]=C;
B1[62]=D;
C1[62]=A;
D1[62]=B;
E1[62]=G;
F1[62]=H;
G1[62]=E;
H1[62]=F;
R2(C, D, A, B, G, H, E, F, 0x9EA1E762, W14, W14 ^ W02);
A1[63]=B;
B1[63]=C;
C1[63]=D;
D1[63]=A;
E1[63]=F;
F1[63]=G;
G1[63]=H;
H1[63]=E;
R2(B, C, D, A, F, G, H, E, 0x3D43CEC5, W15, W15 ^ W03);
ctx->A ^= A;
ctx->B ^= B;
ctx->C ^= C;
ctx->D ^= D;
ctx->E ^= E;
ctx->F ^= F;
ctx->G ^= G;
ctx->H ^= H;
A1[64]=A;
B1[64]=B;
C1[64]=C;
D1[64]=D;
E1[64]=E;
F1[64]=F;
G1[64]=G;
H1[64]=H;
R2(A, B, C, D, E, F, G, H, 0x7A879D8A, W00, W00 ^ W04);
printf("\n扩展后的消息:\n");
for(i=0; i<68; i++) {
printf("W[%02d]=%08x ",i,W[i]);
if(i%8==7) printf("\n");
}
printf("\n\n迭代压缩中间值:\n");
printf(" j A B C D E F G H\n");
printf("----------------------------------------------------------------------------------\n");
for(i=0; i<=64; i++) {
printf("%02d ",i);
printf("%08x ",A1[i]);
printf("%08x ",B1[i]);
printf("%08x ",C1[i]);
printf("%08x ",D1[i]);
printf("%08x ",E1[i]);
printf("%08x ",F1[i]);
printf("%08x ",G1[i]);
printf("%08x\n",H1[i]);
}
}
}
5.md32_common.h
#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# error "DATA_ORDER must be defined!"
#endif
#ifndef HASH_CBLOCK
# error "HASH_CBLOCK must be defined!"
#endif
#ifndef HASH_LONG
# error "HASH_LONG must be defined!"
#endif
#ifndef HASH_CTX
# error "HASH_CTX must be defined!"
#endif
#ifndef HASH_UPDATE
# error "HASH_UPDATE must be defined!"
#endif
#ifndef HASH_TRANSFORM
# error "HASH_TRANSFORM must be defined!"
#endif
#ifndef HASH_FINAL
# error "HASH_FINAL must be defined!"
#endif
#ifndef HASH_BLOCK_DATA_ORDER
# error "HASH_BLOCK_DATA_ORDER must be defined!"
#endif
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++)))<<24), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++))) ) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff), \
l)
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# define HOST_c2l(c,l) (l =(((unsigned long)(*((c)++))) ), \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24) )
# define HOST_l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
l)
#endif
/*
* Time for some action :-)
*/
#include <stdio.h>
int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len) {
const unsigned char *data = data_;
unsigned char *p;
HASH_LONG l;
size_t n;
if (len == 0)
return 1;
l = (c->Nl + (((HASH_LONG) len) << 3)) & 0xffffffffUL;
if (l < c->Nl) /* overflow */
c->Nh++;
c->Nh += (HASH_LONG) (len >> 29); /* might cause compiler warning on
* 16-bit */
c->Nl = l;
n = c->num;
if (n != 0) {
p = (unsigned char *)c->data;
if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
memcpy(p + n, data, HASH_CBLOCK - n);
HASH_BLOCK_DATA_ORDER(c, p, 1);
n = HASH_CBLOCK - n;
data += n;
len -= n;
c->num = 0;
/*
* We use memset rather than OPENSSL_cleanse() here deliberately.
* Using OPENSSL_cleanse() here could be a performance issue. It
* will get properly cleansed on finalisation so this isn't a
* security problem.
*/
memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
} else {
memcpy(p + n, data, len);
c->num += (unsigned int)len;
return 1;
}
}
n = len / HASH_CBLOCK;
if (n > 0) {
HASH_BLOCK_DATA_ORDER(c, data, n);
n *= HASH_CBLOCK;
data += n;
len -= n;
}
if (len != 0) {
p = (unsigned char *)c->data;
c->num = (unsigned int)len;
memcpy(p, data, len);
}
return 1;
}
void HASH_TRANSFORM(HASH_CTX *c, const unsigned char *data) {
HASH_BLOCK_DATA_ORDER(c, data, 1);
}
int HASH_FINAL(unsigned char *md, HASH_CTX *c) {
unsigned char *p = (unsigned char *)c->data;
size_t n = c->num;
p[n] = 0x80; /* there is always room for one */
n++;
if (n > (HASH_CBLOCK - 8)) {
memset(p + n, 0, HASH_CBLOCK - n);
n = 0;
HASH_BLOCK_DATA_ORDER(c, p, 1);
}
memset(p + n, 0, HASH_CBLOCK - 8 - n);
p += HASH_CBLOCK - 8;
#if defined(DATA_ORDER_IS_BIG_ENDIAN)
(void)HOST_l2c(c->Nh, p);
(void)HOST_l2c(c->Nl, p);
#elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
(void)HOST_l2c(c->Nl, p);
(void)HOST_l2c(c->Nh, p);
#endif
p -= HASH_CBLOCK;
HASH_BLOCK_DATA_ORDER(c, p, 1); // 填充后的消息 + 扩展后的消息 + 迭代压缩中间值
c->num = 0;
#ifndef HASH_MAKE_STRING
# error "HASH_MAKE_STRING must be defined!"
#else
HASH_MAKE_STRING(c, md); // Hash值
#endif
return 1;
}
#ifndef MD32_REG_T
# if defined(__alpha) || defined(__sparcv9) || defined(__mips)
# define MD32_REG_T long
/*
* This comment was originally written for MD5, which is why it
* discusses A-D. But it basically applies to all 32-bit digests,
* which is why it was moved to common header file.
*
* In case you wonder why A-D are declared as long and not
* as MD5_LONG. Doing so results in slight performance
* boost on LP64 architectures. The catch is we don't
* really care if 32 MSBs of a 64-bit register get polluted
* with eventual overflows as we *save* only 32 LSBs in
* *either* case. Now declaring 'em long excuses the compiler
* from keeping 32 MSBs zeroed resulting in 13% performance
* improvement under SPARC Solaris7/64 and 5% under AlphaLinux.
* Well, to be honest it should say that this *prevents*
* performance degradation.
*/
# else
/*
* Above is not absolute and there are LP64 compilers that
* generate better code if MD32_REG_T is defined int. The above
* pre-processor condition reflects the circumstances under which
* the conclusion was made and is subject to further extension.
*/
# define MD32_REG_T int
# endif
#endif
(三)运行
compile.sh
gcc sm3test.c src/*.c -o bin/test -Iinclude
bin/test
为 compile.sh 脚本添加执行权限chmod u+x compile.sh
,表示对当前目录下的 compile.sh 文件的所有者增加可执行权限。 u 代表所有者;x 代表执行权限;+ 表示增加权限。
1.测试数据:abc
Hash值:66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
2.测试数据:abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd
Hash值:debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
3.测试数据:20201212
Hash值:30d492ca 6ecc5bea 924665fd c881ea95 770fe474 c388e52c 48b9b400 55d38f68