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相当。
移植过程 一、下载代码从OpenSSL的Github仓库下载代码,可以下载master分支,也可以下载最新的release版本。将下载的文件解压,得到代码。
重点关注红框目录:
- crypto目录内是各种加密算法
- include目录内是各加密算法对外接口的头文件
新建Visual Studio C++ 控制台项目"sm3test",编译选项是:x86Debug
- 复制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
在VS工程中含有main函数的主文件:sm3test.cpp中,增加包含sm3.h头文件
#include "sm3/sm3.h"
在main函数中添加如下代码
SM3_CTX SMC; ossl_sm3_init(&SMC); const unsigned char Data[1024] = "Hello World"; unsigned char md[SM3_DIGEST_LENGTH] = { 0 }; ossl_sm3_update(&SMC, Data, strlen((const char *) Data)); ossl_sm3_final(md, &SMC); for (int i = 0; i < SM3_DIGEST_LENGTH; i++) { printf("%02x-", *(md + i)); }
修改后的sm3test.cpp代码如下:
#include修改sm3.h#include "sm3/sm3.h" int main() { SM3_CTX SMC; ossl_sm3_init(&SMC); const unsigned char Data[1024] = "Hello World"; unsigned char md[SM3_DIGEST_LENGTH] = { 0 }; ossl_sm3_update(&SMC, Data, strlen((const char *) Data)); ossl_sm3_final(md, &SMC); for (int i = 0; i < SM3_DIGEST_LENGTH; i++) { printf("%02x-", *(md + i)); } }
删除条件编译 OPENSSL_SM3_H
删除头文件# include
删除条件编译 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修改sm3_local.h
修改头文件# include "internal/sm3.h"改为#include "sm3.h"
修改头文件# include "crypto/md32_common.h"改为#include "md32_common.h"
修改或删除后的文件如下:
#include修改sm3.c#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
删除头文件#include
修改或删除后的文件如下:
#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; (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; } }修改md32_common.h
删除头文件# include
删除代码中全部的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 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) c->Nh++; c->Nh += (HASH_LONG) (len >> 29); 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; memset(p, 0, HASH_CBLOCK); } 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; 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 # else # define MD32_REG_T int # endif #endif五、编译运行
将sm3.h,sm3.c,sm3_local.h,md32_common.h文件,配置添加到VS工程中。
编译运行,输出sm3结果如下:
77-01-58-16-14-3e-e6-27-f4-fa-41-0b-6d-ad-2b-db-9f-cb-df-1e-06-1a-45-2a-68-6b-87-11-a4-84-c5-d7
上述算法,适用于计算字符串、缓冲区的SM3值。至于小文件、大文件的SM3如何计算,可以参考本人的另外两篇关于MD5的博客,与SM3非常相似。
小文件MD5计算
大文件MD5计算
欢迎大家关注、留言讨论、可分享源码
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)