算法过程

代码实现

国标

/************************************************************************
File name: SM3.c
Version: SM3_V1.1
Date: Sep 18,2016
Description: to calculate a hash message from a given message
Function List:
1.SM3_256 //calls SM3_init, SM3_process and SM3_done to calculate hash value
2.SM3_init //init the SM3 state
3.SM3_process //compress the the first len/64 blocks of the message
4.SM3_done //compress the rest message and output the hash value
5.SM3_compress //called by SM3_process and SM3_done, compress a single block of message
6.BiToW //called by SM3_compress,to calculate W from Bi
7.WToW1 //called by SM3_compress, calculate W1 from W
8.CF //called by SM3_compress, to calculate CF function.
9.BigEndian //called by SM3_compress and SM3_done.GM/T 0004-2012 requires to use
big-endian.
//if CPU uses little-endian, BigEndian function is a necessary call to
change the
//little-endian format into big-endian format.
10.SM3_SelfTest //test whether the SM3 calculation is correct by comparing the hash result
with the standard result
History:
1. Date: Sep 18,2016
Author: Mao Yingying, Huo Lili
Modification: 1)add notes to all the functions
2)add SM3_SelfTest function
**************************************************************************/
#include "SM3.h" /******************************************************************************
Function: inputChar
Description: 输出
*******************************************************************************/
void inputChar(unsigned char* Msg, int len)
{
int i,count=0;
for (i = 0; i < len; i++)
{
printf("%02X\t", Msg[i]);
count++;
if ( count%8 == 0)
{
printf("\n");
}
}
} /******************************************************************************
Function: inputInt
Description: 输出
*******************************************************************************/
void inputInt(unsigned int* Msg, int len)
{
int i, count = 0;
for (i = 0; i < len; i++)
{
printf("%08X\t", Msg[i]);
count++;
if (count % 8 == 0)
{
printf("\n");
}
}
} /****************************************************************
Function: BiToW
Description: calculate W from Bi【消息扩展】
Calls:
Called By: SM3_compress
Input: Bi[16] //a block of a message
Output: W[64]
Return: null
Others: 将消息分组B[i]扩展生成132个消息字W和W1,这里生成的是W
****************************************************************/
void BiToW(unsigned int Bi[], unsigned int W[])
{
int i,count=0;
unsigned int tmp;
//消息扩展-A
//将消息分组B[i]划分为16个字W[i]
for (i = 0; i <= 15; i++)
{
W[i] = Bi[i];
}
//消息扩展-B
for (i = 16; i <= 67; i++)
{
tmp = W[i - 16]^ W[i - 9]^ SM3_rotl32(W[i - 3], 15);
W[i] = SM3_p1(tmp)^ (SM3_rotl32(W[i - 13], 7))^ W[i - 6];
}
inputInt(W, 68);
} /*****************************************************************
Function: WToW1
Description: calculate W1 from W
Calls:
Called By: SM3_compress
Input: W[64]
Output: W1[64]
Return: null
Others: 将消息分组B[i]扩展生成132个消息字W和W1,这里生成的是W1
*****************************************************************/
void WToW1(unsigned int W[], unsigned int W1[])
{
int i;
//消息扩展-C,生成W1
for (i = 0; i <= 63; i++)
{
W1[i] = W[i] ^ W[i + 4];
}
inputInt(W1, 64);
} /******************************************************************
Function: CF
Description: calculate the CF compress function and update V【压缩函数】
Calls:
Called By: SM3_compress
Input: W[64]
W1[64]
V[8]
Output: V[8]
Return: null
Others:
********************************************************************/
void CF(unsigned int W[], unsigned int W1[], unsigned int V[])
{
unsigned int SS1;
unsigned int SS2;
unsigned int TT1;
unsigned int TT2;
unsigned int A, B, C, D, E, F, G, H;
unsigned int T = SM3_T1;
unsigned int FF;
unsigned int GG;
int j;
printf("\n\n迭代压缩后的中间值:"); //ABCDEFGH=V0
A = V[0];
B = V[1];
C = V[2];
D = V[3];
E = V[4];
F = V[5];
G = V[6];
H = V[7];
printf("\nj\tA\t B\t C\t D\t E\t F\t G\t H\n");
printf("\n\t%08X %08X %08X %08X %08X %08X %08X %08X\n", A, B, C, D, E, F, G, H);
for (j = 0; j <= 63; j++)
{
//SS1
if (j == 0)
{
T = SM3_T1;
}
else if (j == 16)
{
T = SM3_rotl32(SM3_T2, 16);
}
else
{
T = SM3_rotl32(T, 1);
}
SS1 = SM3_rotl32((SM3_rotl32(A, 12) + E + T), 7); //SS2
SS2 = SS1 ^ SM3_rotl32(A, 12); //TT1
if (j <= 15)
{
FF = SM3_ff0(A, B, C);
} else
{
FF = SM3_ff1(A, B, C);
}
TT1 = FF + D + SS2 + *W1;
W1++; //TT2
if (j <= 15)
{
GG = SM3_gg0(E, F, G);
}
else
{
GG = SM3_gg1(E, F, G);
}
TT2 = GG + H + SS1 + *W;
W++; //D
D = C; //C
C = SM3_rotl32(B, 9); //B
B = A; //A
A = TT1; //H
H = G; //G
G = SM3_rotl32(F, 19); //F
F = E; //E
E = SM3_p0(TT2); printf("\n%d\t%08X %08X %08X %08X %08X %08X %08X %08X\n", j,A, B, C, D, E, F, G, H);
} //update V
V[0] = A ^ V[0];
V[1] = B ^ V[1];
V[2] = C ^ V[2];
V[3] = D ^ V[3];
V[4] = E ^ V[4];
V[5] = F ^ V[5];
V[6] = G ^ V[6];
V[7] = H ^ V[7];
} /******************************************************************************
Function: BigEndian
Description: 大端,高字节存放在低地址,低字节存放在高地址
Calls:
Called By: SM3_compress, SM3_done
Input: src[bytelen]
bytelen
Output: des[bytelen]
Return: null
Others: src and des could implies the same address
*******************************************************************************/
void BigEndian(unsigned char src[], unsigned int bytelen, unsigned char des[])
{
unsigned char tmp = 0;
unsigned int i = 0; for (i = 0; i < bytelen / 4; i++)
{
tmp = des[4 * i];
des[4 * i] = src[4 * i + 3];
src[4 * i + 3] = tmp; tmp = des[4 * i + 1];
des[4 * i + 1] = src[4 * i + 2];
des[4 * i + 2] = tmp;
}
} /******************************************************************************
Function: SM3_init
Description: initiate SM3 state
Calls:
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_init(SM3_STATE* md)
{
//将IV存于md->state中,即V中
md->curlen = md->length = 0;
md->state[0] = SM3_IVA;
md->state[1] = SM3_IVB;
md->state[2] = SM3_IVC;
md->state[3] = SM3_IVD;
md->state[4] = SM3_IVE;
md->state[5] = SM3_IVF;
md->state[6] = SM3_IVG;
md->state[7] = SM3_IVH;
} /******************************************************************************
Function: SM3_compress
Description: compress a single block of message
Calls: BigEndian
BiToW
WToW1
CF
Called By: SM3_256
Input: SM3_STATE *md
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_compress(SM3_STATE* md)
{
//将消息分组B[i]扩展生成132个消息字W0,W1,...,W67,W'0,W'1,...,W'63
unsigned int W[68]; //存储W
unsigned int W1[64]; //存储W' //字存储为大端格式,坐标为高有效位,右边为低有效位
BigEndian(md->buf, 64, md->buf); //消息扩展
printf("\n\n扩展后的消息:");
printf("\n\n*******W0,W1,...,W67*******:\n");
BiToW((unsigned int*)md->buf, W);
printf("\n\n*******W'0,W'1,...,W'63*******:\n");
WToW1(W, W1); //压缩函数(W,W1,V[i])
CF(W, W1, md->state);
} /******************************************************************************
Function: SM3_process
Description: compress the first (len/64) blocks of message【迭代过程】
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
unsigned char buf[len] //the input message
int len //bytelen of message
Output: SM3_STATE *md
Return: null
Others:
*******************************************************************************/
void SM3_process(SM3_STATE* md, unsigned char* buf, int len)
{
//将填充后的消息m'按512比特进行分组为B0,B1,...,Bn-1
int n = 1;//消息分组的个数
while (len--)
{
/* copy byte */
md->buf[md->curlen] = *buf++;
md->curlen++; /* is 64 bytes full? 即是否是512比特为一组*/
if (md->curlen == 64)
{
printf("\n\n第%d个消息分组:\n\n",n);
SM3_compress(md);
md->length += 512;
n++;
md->curlen = 0;
}
}
} /******************************************************************************
Function: SM3_done
Description: compress the rest message that the SM3_process has left behind
Calls: SM3_compress
Called By: SM3_256
Input: SM3_STATE *md
Output: unsigned char *hash
Return: null
Others:
*******************************************************************************/
void SM3_done(SM3_STATE* md, unsigned char hash[])
{
int i,count=1;
unsigned char tmp = 0; /* increase the bit length of the message 增长1字节的长度*/
md->length += md->curlen << 3; /* append the '1' bit 首先将比特'1'添加到消息的末尾*/
md->buf[md->curlen] = 0x80;
md->curlen++; /* if the length is currently above 56 bytes, appends zeros till
it reaches 64 bytes, compress the current block, creat a new
block by appending zeros and length,and then compress it
若当前长度超过56字节(512比特),则添加0直到64字节,然后迭代压缩
*/
if (md->curlen > 56)
{
for (; md->curlen < 64;)
{
md->buf[md->curlen] = 0;
md->curlen++;
}
//64字节为一组进行迭代压缩
SM3_compress(md);
//长度置0,重新创建新块
md->curlen = 0;
} /* if the length is less than 56 bytes, pad upto 56 bytes of zeroes
若长度小于56字节,则填充0至56个字节
*/
for (; md->curlen < 56;)
{
md->buf[md->curlen] = 0;
md->curlen++;
} /* since all messages are under 2^32 bits we mark the top bits zero
由于所有消息都在2^32位以下,故将最高位标记为0
*/
for (i = 56; i < 60; i++)
{
md->buf[i] = 0;
} /* append length 添加一个64比特串,该比特串是长度为l的二进制表示*/
md->buf[63] = md->length & 0xff;
md->buf[62] = (md->length >> 8) & 0xff;
md->buf[61] = (md->length >> 16) & 0xff;
md->buf[60] = (md->length >> 24) & 0xff; printf("\n*******填充后的消息*******:\n");
inputChar(md->buf, 64); SM3_compress(md); /* copy output */
memcpy(hash, md->state, SM3_len / 8);
//if CPU uses little-endian, BigEndian function is a necessary call
BigEndian(hash, SM3_len / 8, hash);
} /******************************************************************************
Function: SM3_256
Description: calculate a hash value from a given message
Calls: SM3_init
SM3_process
SM3_done
Called By:
Input: unsigned char buf[len] //the input message
int len //bytelen of the message
Output: unsigned char hash[32]
Return: null
Others:
*******************************************************************************/
void SM3_256(unsigned char buf[], int len, unsigned char hash[])
{
SM3_STATE md;
SM3_init(&md);
SM3_process(&md, buf, len);
SM3_done(&md, hash);
} /******************************************************************************
Function: SM3_SelfTest
Description: test whether the SM3 calculation is correct by comparing
the hash result with the standard result
Calls: SM3_256
Called By:
Input: null
Output: null
Return: 0 //the SM3 operation is correct
1 //the sm3 operation is wrong
Others:
*******************************************************************************/
void SM3_SelfTest()
{
unsigned int i = 0, a = 1, b = 1;
int choose;
printf("请选择输入示例:1.示例1\t\t2.示例2\n");
scanf("%d", &choose); if (choose == 1)
{
//示例1
unsigned char Msg1[3] = { 0x61,0x62,0x63 };// ASCII码
int MsgLen1 = 3;
unsigned char MsgHash1[32] = { 0 }; //生成的Hash值
printf("\n*******输入的字符串消息*******:\n");
inputChar(Msg1, MsgLen1); /*
unsigned char StdHash1[32] = { 0x66,0xC7,0xF0,0xF4,0x62,0xEE,0xED,0xD9,0xD1,0xF2,0xD4,0x6B,0xDC,0x10,0xE4,0xE2,
0x41,0x67,0xC4,0x87,0x5C,0xF2,0xF7,0xA2,0x29,0x7D,0xA0,0x2B,0x8F,0x4B,0xA8,0xE0 };//已经计算好的Hash值
*/
SM3_256(Msg1, MsgLen1, MsgHash1);
printf("\n*******输出杂凑值*******:\n");
inputChar(MsgHash1, 32);
}
else if (choose == 2)
{
//示例2
unsigned char Msg2[64] = { 0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64 };// ASCII码
int MsgLen2 = 64;
unsigned char MsgHash2[32] = { 0 };//生成的Hash值
printf("\n*******输入的字符串消息*******:\n");
inputChar(Msg2, MsgLen2); /*
unsigned char StdHash2[32] = { 0xde,0xbe,0x9f,0xf9,0x22,0x75,0xb8,0xa1,0x38,0x60,0x48,0x89,0xc1,0x8e,0x5a,0x4d,
0x6f,0xdb,0x70,0xe5,0x38,0x7e,0x57,0x65,0x29,0x3d,0xcb,0xa3,0x9c,0x0c,0x57,0x32 };//已经计算好的Hash值
*/
SM3_256(Msg2, MsgLen2, MsgHash2);
printf("\n*******输出杂凑值*******:\n");
inputChar(MsgHash2, 32);
}
else
printf("输入错误,请重新输入!\n"); //比较是否相同
/*
a = memcmp(MsgHash1, StdHash1, SM3_len / 8);
b = memcmp(MsgHash2, StdHash2, SM3_len / 8); if ((a == 0) && (b == 0))
{
return 0;
}
else
{
return 1;
}
*/
} int main()
{
printf("*********************************************************\n");
printf("*\t\t\tSM3密码杂凑算法\t\t\t*\n");
printf("*********************************************************\n\n");
SM3_SelfTest();
printf("\n");
system("pause");
return 0;
}

openSSL中提取

参考:SM3算法 C语言 (从OpenSSL库中分离算法:六)

#include <iostream>
#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 }; printf("input message:%s\n",Data);
ossl_sm3_update(&SMC, Data, strlen((const char *) Data));
ossl_sm3_final(md, &SMC); printf("output hash value:");
for (int i = 0; i < SM3_DIGEST_LENGTH; i++) {
printf("%02x ", *(md + i));
}
}

注:代码见github

参考

1、国标-SM3

2、商用密码检测中心-源码下载

3、密码学-基础理论与应用(李子臣著)

SM3的更多相关文章

  1. KlayGE 4.4中渲染的改进(一):只需要SM3的TBDR

    转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2736 KlayGE从4.0开始引入deferred rendering层(DR),并且这几个 ...

  2. Shader Model 3.0:Using Vertex Textures SM3:使用顶点纹理 (NVIDIA spec, 6800支持使用D3DFMT_R32F and D3DFMT_A32B32G32R32F的纹理格式实现Vertex Texture。)

    翻译者 周波 zhoubo22@hotmail.com 版权所有 Philipp Gerasimov Randima (Randy) Fernando Simon Green NVIDIA Corpo ...

  3. AES SHA-1 SM3 MD5

    AES是美国国家标准技术研究所NIST旨在代替DES的21世纪的加密标准. 输入:128bit 的消息分组 输出:128bit 的密文分组 密钥长度及圈数 128 10 192 12 256 14 消 ...

  4. SM3杂凑算法Python语言实现——第三部分

    SM3杂凑算法实现--第三部分 一.SM3 密码概述        我们首先把需要用到的算法呈现出来,最后我们再考虑如何集合为一个库的方法,这一部分我们就开始编写一个新的算法:国家商用密码标准SM3密 ...

  5. 国密SM3算法在linux和windows平台结果不一致问题

    什么是sm3,是一种类似于sha256的哈希算法,是咱们国家的哈希标准算法: 最近在使用sm3算法时,同样的一份数据,调用同样的sm3接口,发现得到的结果是不一样的: 那么在应用过的过程中,如果同样的 ...

  6. Expanded encryption and decryption signature algorithm SM2 & SM3

    Expanded encryption and decryption signature algorithm supports multiple signature digest algorithms ...

  7. 关于国密算法 SM1,SM2,SM3,SM4 的笔记

    国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接 ...

  8. java sm3加密算法

      java sm3加密算法实现 CreationTime--2018年7月13日09点28分 Author:Marydon 1.准备工作 所需jar包: bcprov-jdk15on-1.59.ja ...

  9. 毕业设计预习:SM3密码杂凑算法基础学习

    SM3密码杂凑算法基础学习 术语与定义 1 比特串bit string 由0和1组成的二进制数字序列. 2 大端big-endian 数据在内存中的一种表示格式,规定左边为高有效位,右边为低有效位.数 ...

  10. SM3算法

    /* * sm3.h * * 为使此算法兼容32位.64位下Linux或Windows系统, * 选择 int 来表示 32 位整数. * 消息长度最大限定为 2**32 - 1(单位:比特), * ...

随机推荐

  1. 推荐一个.NetCore开源的CMS项目,功能强大、扩展性强、支持插件的系统!

    推荐一个基于.Net Core开发的开源CMS项目,该项目功能完善.涉及知识点比较多,不管是作为二次开发.还是学习都是不错的选择. 01 项目简介 Cofoundry是基于.Net开发的.代码优先开发 ...

  2. 卡特兰数 Catalan 数列

    卡特兰数 Catalan 数列 引入 有一个无限大的栈,进栈的顺序为 \(1,2,\cdots,n\),求有多少种不同的出栈序列. 设 \(h[n]\) 为 \(n\) 个数的出栈序列方案数. 可以这 ...

  3. 十分钟配置完成Go开发环境

    本文介绍了GO环境搭建以及GOPATH.GOROOT等基本概念,希望让你少走弯路 SDK下载 如果要使用Golang,我们首先要安装Golang的SDK开发包 Golang是网友给Go语言起的另一个称 ...

  4. Java线程池架构2-多线程调度器

      http://ifeve.com/java线程池架构2-多线程调度器(scheduledthreadpoolexecutor)/ 在前面介绍了java的多线程的基本原理信息:<Java线程池 ...

  5. Shiro 漏洞复现

    Shiro 漏洞复现 shiro是什么? ApacheShiro是一个灵活且全面的Java安全框架,它为现代应用程序提供了认证.授权.加密和会话管理等核心安全功能. shiro组件识别 1.在访问及登 ...

  6. 版本管理客户端工具SourceTree

    [使用] 1.设置SSH客户端 工具 > 选项 设置OpenSSH, SSH 密钥这一栏自然会去选择当前用户下的 .ssh 目录下的 id_rsa 这个私钥:

  7. 专为移动端设计的PDF阅读器-小白PDF阅读器

    以前在手机端看扫描版的pdf电子书,要么放大后用手指来回拖动着看,要么将手机横屏看,阅读体验非常差!后来就想自己做一款能自动重排版的pdf阅读器,于是小白PDF阅读器就诞生了! 小白PDF阅读器的重排 ...

  8. groovy 内存回收测试

    问题 在使用我们的开发平台时,客户怀疑我们的动态执行脚本会导致系统内存回收的问题,导致系统不响应,为此我专门针对这个问题,做一下详细的测试,看看是不是到底有什么影响. 测试步骤 1.使用编写一个控制器 ...

  9. 【自制FOC驱动器】深入浅出讲解FOC算法与SVPWM技术

    转载自 http://www.pengzhihui.xyz/2020/07/02/foc/ 前言前阵子工作太忙,好久没做个人项目了,最近久违地想做一个机器人项目,设计中需要用到高性能超小体积的伺服电机 ...

  10. 【Python】2023年Python期末复习题

    Python百分百挂科指南 出题人,出的题,水平不咋样,给出的参考答案一堆错误,给出的正确选项单词都能拼错. 非本次考试人员不必看,没有参考价值 选择题 下列哪个标识符是不合法的()D A. Name ...