SM3算法 C语言 (从OpenSSL库中分离算法)

一、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目录内是各加密算法对外接口的头文件
    image

(二)准备环境

新建Visual Studio C++ 控制台项目"sm3test",编译选项是:x86\Debug
image
image

(三)准备文件

  1. 复制OpenSSL源码中:/crypto/sm3文件夹到VS工程代码目录下
  2. 复制OpenSSL源码中:/include/internal/sm3.h文件到VS工程代码目录中sm3文件夹内
  3. 复制OpenSSL源码中:/include/crypto/md32_common.h文件到VS工程代码目录中sm3文件夹内
  4. 复制完成后,VS工程代码目录sm3文件夹内文件如下:
    image

删除目录内的如下本项目中无用文件:

  • build.info
  • legacy_sm3.c
    image

(四)修改代码

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工程中。
image
编译运行,输出sm3结果如下:

输入数据:abc
Hash值:66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0

image

四、Ubuntu上运行(Linux)

(一)目录结构

image

(二)代码

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

image
image
image

2.测试数据:abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd

Hash值:debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732

image
image
image

3.测试数据:20201212

Hash值:30d492ca 6ecc5bea 924665fd c881ea95 770fe474 c388e52c 48b9b400 55d38f68

image
image
image

posted @ 2023-05-10 11:27  油菜园12号  阅读(347)  评论(0编辑  收藏  举报