精华内容
下载资源
问答
  • 2021-06-19 21:10:04

    【实验目的】

    1、理解Hash函数的计算原理和特点
    2、理解SM3算法原理
    3、了解SM3值的生成过程

    【实验环境】

    用户A需要生成一段消息的SM3值,准备依据这个散列值对消息进行进一步的处理。
    完成本实验需要使用密码学教学软件,在D:\Release\bin目录下打开Crypto软件。

    【实验预备知识点】

    SM3算法是密码杂凑算法,适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。
    对长度为l(l< 2^64) 比特的消息m,SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度为256比特。具体过程请见SM3标准描述。

    【实验内容】

    SM3算法是国家密码管理局2010年12月颁布的密码杂凑算法,适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成。

    SM3算法对于长度小于264位的消息,产生一个256位的消息摘要。

    算法以512位分组来处理输入的信息,每一分组又被划分为132个32位子分组,经过一系列的处理后,算法的输出由八个32位分组组成,将这些32位分组级联后产生一个256位的散列值。

    【实验步骤】

    (1). 输入消息
    (2). 点击生成按钮
    (3). 观察明文填充块,观察生成的散列值
    (4). 点击64步运算按钮,观察SM3运算的各个步骤
    (5). 对输入消息做细微修改
    (6). 重复(2),(3),(4)
    (7). 比较散列值前后的变化情况
    操作说明
    本演示实验以一个分组(512位)的散列计算为例,考虑到填充的信息长度,用户输入的长度不超过55个字节,超过部分系统会自动截断。

    (1)进入SM3演示程序
    点击教学软件中的SM算法的SM3算法。
    (2) 输入待散列的明文
    (3) 生成散列值
    点击生成,系统首先显示填充后的512位子明文分组,然后依据算法产生相应的子明文分组扩充,最后显示生成的SHA1散列值。
    在这里插入图片描述
    图 1生成散列值
    (4)详细计算流程
    点击64步运算按钮,系统显示对明文数据进行运算的80步操作细节。
    在这里插入图片描述
    图 2详细计算流程
    点击步骤,可以依序得到每步的计算结果
    在这里插入图片描述
    图 3得到每步计算结果

    【实验思考题】

    1、 SM3的基本处理块大小如何?
    (1) 算法的本质
    给数据加一个固定长度的指纹,这个固定长度就是256比特。
    (2) 处理过程
    第一步:填充,使填充后的数据的长度是512的整数倍
    先在数据的最尾巴上加一个1;然后把原始数据的长度用64比特表示,放在最后面;再看看现在的数据的长度值离512的整数还差多少个,差多少个就填多少个0在加的这个1和64比特的长度之间。
    (3) 分组
    把填充后的信息按照512比特一个分组进行分组,如果分成了N组,就是b(0),b(1),b(N-1)
    第三步:迭代压缩得到最后的杂凑值(哈希值)
    IV(n)=CF(IV(n-1),b(n-1))
    如果信息分为N组,那么IV(N)就是最后得到的杂凑值。

    2、 SM3与MD5,SHA1的散列值的大小分别是多少?
    (1) SM3算法对于长度小于264位的消息,产生一个256位的消息摘要。算法以512位分组来处理输入的信息,每一分组又被划分为132个32位子分组,经过一系列的处理后,算法的输出由八个32位分组组成,将这些32位分组级联后产生一个256位的散列值。

    (2) MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。

    (3) SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

    更多相关内容
  • C#国密加密算法SM3一个实现案例代码。 说明如下: 1、BouncyCastle.Crypto:工程需要引用的原始库(不会引用直接百度即可); 2、sm3.cs:SM3算法主体内容。 另:为了提高可读性及便于理解,代码流程的说明与标准...
  • SM3算法及HMAC<SM3>算法C语言实现。内附详细测试例程。 SM3测试数据取自 GMT 0004-2012 HMAC测试数据来自Crypto++ 源文件列表: test.cpp sm3.cpp sm3.h 包含测试工程: VC++6.0, VC++2008, VC++2013, CentOS7-x64+...
  • 国密sm3算法js版

    2018-10-09 17:17:25
    国密sm3算法js版,可实现对密码进行sm3算法加密。资源包含示例、所选js及包,可直接测试使用。
  • SM3算法原理

    2012-06-05 07:54:54
    SM3算法原理,朋友亲自整理的,供大家交流学习。
  • SM3算法实现,商用密码体系算法,++++++++++++++++++++=====
  • SM3算法的编程实现

    千次阅读 2021-06-19 21:04:51
    SM3算法的编程实现SM3算法的编程实现【实验目的】【实验环境】【实验预备知识点】【实验步骤】【实验思考题】 SM3算法的编程实现 【实验目的】 1、理解Hash函数的计算原理和特点; 2、理解SM3算法原理; 3、了解SM3...

    SM3算法的编程实现

    【实验目的】

    1、理解Hash函数的计算原理和特点;
    2、理解SM3算法原理;
    3、了解SM3值的生成过程。

    【实验环境】

    windows虚拟机
    在目录C:\Program Files\Microsoft Visual Studio\MyProjects\SM3 下打开SM3.dsw,在VC6.0环境下编译代码。

    【实验预备知识点】

    设消息m的长度为l bit,首先将bit"1"添加到消息末尾,再加k个“0”,k是满足l+1+k =448 mod 512的最小非负整数。然后再添加一个64bit串,该串是l的二进制表示,填充后的消息m’长度为512的整数倍。填充过后,再经迭代压缩,最后经过散列运算即可得到结果。

    1. 主流程图
      在这里插入图片描述

    图 1主流程图
    在这里插入图片描述

    1. 程序调用层次图

    在这里插入图片描述
    图 2程序调用关系图.

    1. 程序调用关系图
      在这里插入图片描述
      图 3程序调用关系图.
      【实验内容】
      SM3算法是国家密码管理局2010年12月颁布的密码杂凑算法,适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成。SM3算法对于长度小于264位的消息,产生一个256位的消息摘要。算法以512位分组来处理输入的信息,每一分组又被划分为132个32位子分组,经过一系列的处理后,算法的输出由八个32位分组组成,将这些32位分组级联后产生一个256位的散列值。

    【实验步骤】

    以下是程序的关键代码:

    //SM3.C
    void sm3_starts( sm3_context *ctx )
    {
        ctx->total[0] = 0;
        ctx->total[1] = 0;
        ctx->state[0] = 0x7380166F;
        ctx->state[1] = 0x4914B2B9;
        ctx->state[2] = 0x172442D7;
        ctx->state[3] = 0xDA8A0600;
        ctx->state[4] = 0xA96F30BC;
        ctx->state[5] = 0x163138AA;
        ctx->state[6] = 0xE38DEE4D;
        ctx->state[7] = 0xB0FB0E4E;
    }
     
    static void sm3_process( sm3_context *ctx, unsigned char data[64] )
    {
        unsigned long SS1, SS2, TT1, TT2, W[68],W1[64];
        unsigned long A, B, C, D, E, F, G, H;
        unsigned long T[64];
        unsigned long Temp1,Temp2,Temp3,Temp4,Temp5;
        int j;
     
     
     
       
        for(j = 0; j < 16; j++)
           T[j] = 0x79CC4519;
        for(j =16; j < 64; j++)
           T[j] = 0x7A879D8A;
     
        GET_ULONG_BE( W[ 0], data,  0 );
        GET_ULONG_BE( W[ 1], data,  4 );
        GET_ULONG_BE( W[ 2], data,  8 );
        GET_ULONG_BE( W[ 3], data, 12 );
        GET_ULONG_BE( W[ 4], data, 16 );
        GET_ULONG_BE( W[ 5], data, 20 );
        GET_ULONG_BE( W[ 6], data, 24 );
        GET_ULONG_BE( W[ 7], data, 28 );
        GET_ULONG_BE( W[ 8], data, 32 );
        GET_ULONG_BE( W[ 9], data, 36 );
        GET_ULONG_BE( W[10], data, 40 );
        GET_ULONG_BE( W[11], data, 44 );
        GET_ULONG_BE( W[12], data, 48 );
        GET_ULONG_BE( W[13], data, 52 );
        GET_ULONG_BE( W[14], data, 56 );
        GET_ULONG_BE( W[15], data, 60 );
     
    #define FF0(x,y,z) ( (x) ^ (y) ^ (z))
    #define FF1(x,y,z) (((x) & (y)) | ( (x) & (z)) | ( (y) & (z)))
    #define GG0(x,y,z) ( (x) ^ (y) ^ (z))
    #define GG1(x,y,z) (((x) & (y)) | ( (~(x)) & (z)) )
    #define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
    #define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
     
    #define P0(x) ((x) ^  ROTL((x),9) ^ ROTL((x),17))
    #define P1(x) ((x) ^  ROTL((x),15) ^ ROTL((x),23))
     
        for(j = 16; j < 68; j++ )
        {
           Temp1 = W[j-16] ^ W[j-9];
           Temp2 = ROTL(W[j-3],15);
           Temp3 = Temp1 ^ Temp2;
           Temp4 = P1(Temp3);
           Temp5 =  ROTL(W[j - 13],7 ) ^ W[j-6];
           W[j] = Temp4 ^ Temp5;
        }
        for(j =  0; j < 64; j++)
        {
            W1[j] = W[j] ^ W[j+4];
        }
        A = ctx->state[0];
        B = ctx->state[1];
        C = ctx->state[2];
        D = ctx->state[3];
        E = ctx->state[4];
        F = ctx->state[5];
        G = ctx->state[6];
        H = ctx->state[7];
        for(j =0; j < 16; j++)
        {
           SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7);
           SS2 = SS1 ^ ROTL(A,12);
           TT1 = FF0(A,B,C) + D + SS2 + W1[j];
           TT2 = GG0(E,F,G) + H + SS1 + W[j];
           D = C;
           C = ROTL(B,9);
           B = A;
           A = TT1;
           H = G;
           G = ROTL(F,19);
           F = E;
           E = P0(TT2);
        }
        for(j =16; j < 64; j++)
        {
           SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7);
           SS2 = SS1 ^ ROTL(A,12);
           TT1 = FF1(A,B,C) + D + SS2 + W1[j];
           TT2 = GG1(E,F,G) + H + SS1 + W[j];
           D = C;
           C = ROTL(B,9);
           B = A;
           A = TT1;
           H = G;
           G = ROTL(F,19);
           F = E;
           E = P0(TT2);
        }
     
        ctx->state[0] ^= A;
        ctx->state[1] ^= B;
        ctx->state[2] ^= C;
        ctx->state[3] ^= D;
        ctx->state[4] ^= E;
        ctx->state[5] ^= F;
        ctx->state[6] ^= G;
        ctx->state[7] ^= H;
     
    } 
    void sm3_update( sm3_context *ctx, unsigned char *input, int ilen )
    {
        int fill;
        unsigned long left;
     
        if( ilen <= 0 )
            return;
        left = ctx->total[0] & 0x3F;
        fill = 64 - left;
        ctx->total[0] += ilen;
        ctx->total[0] &= 0xFFFFFFFF;
        if( ctx->total[0] < (unsigned long) ilen )
            ctx->total[1]++;
        if( left && ilen >= fill )
        {
            memcpy( (void *) (ctx->buffer + left),
                    (void *) input, fill );
            sm3_process( ctx, ctx->buffer );
            input += fill;
            ilen  -= fill;
            left = 0;
        }
        while( ilen >= 64 )
        {
            sm3_process( ctx, input );
            input += 64;
            ilen  -= 64;
        }
        if( ilen > 0 )
        {
            memcpy( (void *) (ctx->buffer + left),
                    (void *) input, ilen );
        }
    }
     
    static const unsigned char sm3_padding[64] =
    {
     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    };
     
    void sm3_finish( sm3_context *ctx, unsigned char output[32] )
    {
        unsigned long last, padn;
        unsigned long high, low;
        unsigned char msglen[8];
     
        high = ( ctx->total[0] >> 29 )
             | ( ctx->total[1] <<  3 );
        low  = ( ctx->total[0] <<  3 );
        PUT_ULONG_BE( high, msglen, 0 );
        PUT_ULONG_BE( low,  msglen, 4 );
        last = ctx->total[0] & 0x3F;
        padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
        sm3_update( ctx, (unsigned char *) sm3_padding, padn );
        sm3_update( ctx, msglen, 8 );
        PUT_ULONG_BE( ctx->state[0], output,  0 );
        PUT_ULONG_BE( ctx->state[1], output,  4 );
        PUT_ULONG_BE( ctx->state[2], output,  8 );
        PUT_ULONG_BE( ctx->state[3], output, 12 );
        PUT_ULONG_BE( ctx->state[4], output, 16 );
        PUT_ULONG_BE( ctx->state[5], output, 20 );
        PUT_ULONG_BE( ctx->state[6], output, 24 );
        PUT_ULONG_BE( ctx->state[7], output, 28 );
    }
    void sm3( unsigned char *input, int ilen,
               unsigned char output[32] )
    {
        sm3_context ctx;
        sm3_starts( &ctx );
        sm3_update( &ctx, input, ilen );
        sm3_finish( &ctx, output );
     
        memset( &ctx, 0, sizeof( sm3_context ) );
    }
    int sm3_file( char *path, unsigned char output[32] )
    {
        FILE *f;
        size_t n;
        sm3_context ctx;
        unsigned char buf[1024];
        if( ( f = fopen( path, "rb" ) ) == NULL )
            return( 1 );
        sm3_starts( &ctx );
        while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
            sm3_update( &ctx, buf, (int) n );
        sm3_finish( &ctx, output );
        memset( &ctx, 0, sizeof( sm3_context ) );
        if( ferror( f ) != 0 )
        {
            fclose( f );
            return( 2 );
        }
        fclose( f );
        return( 0 );
    }
    void sm3_hmac_starts( sm3_context *ctx, unsigned char *key, int keylen )
    {
        int i;
        unsigned char sum[32];
     
        if( keylen > 64 )
        {
            sm3( key, keylen, sum );
            keylen = 32;
            key = sum;
        }
        memset( ctx->ipad, 0x36, 64 );
        memset( ctx->opad, 0x5C, 64 );
        for( i = 0; i < keylen; i++ )
        {
            ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
            ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
        }
        sm3_starts( ctx);
        sm3_update( ctx, ctx->ipad, 64 );
     
        memset( sum, 0, sizeof( sum ) );
    }
    void sm3_hmac_update( sm3_context *ctx, unsigned char *input, int ilen )
    {
        sm3_update( ctx, input, ilen );
    }
    void sm3_hmac_finish( sm3_context *ctx, unsigned char output[32] )
    {
        int hlen;
        unsigned char tmpbuf[32];
        hlen =  32;
        sm3_finish( ctx, tmpbuf );
        sm3_starts( ctx );
        sm3_update( ctx, ctx->opad, 64 );
        sm3_update( ctx, tmpbuf, hlen );
        sm3_finish( ctx, output );
        memset( tmpbuf, 0, sizeof( tmpbuf ) );
    }
    void sm3_hmac( unsigned char *key, int keylen,
                    unsigned char *input, int ilen,
                    unsigned char output[32] )
    {
        sm3_context ctx;
        sm3_hmac_starts( &ctx, key, keylen);
        sm3_hmac_update( &ctx, input, ilen );
        sm3_hmac_finish( &ctx, output );
        memset( &ctx, 0, sizeof( sm3_context ) );
    }
    

    程序运行结果
    输入明文1234abc,得到相应的消息摘要
    在这里插入图片描述
    图 4程序运行结果.

    【实验思考题】

    1. 请总结SM3与MD5,SHA1的异同。
      (1) 算法结构不同
      在消息填充方面,几个hash算法基本相同,都是先在原始消息的最后加一位“1”,再添加k个“0”,最终要使l+1+k除以512后的余数为448,取其最小的非负整数。然后用一个64位的比特串标识原始消息的长度l。填充后的消息M正好是512位的倍数。(其中)
      SM3算法的压缩函数与SHA-256的压缩函数具有相似的结构,但是SM3算法的设计更加复杂,比如压缩函数的每一轮都使用2个消息字。

    (2) 安全性不同
    摘要函数在密码学中具有重要的地位,被广泛应用在数字签名,消息认证,数据完整性检测等领域。摘要函数通常被认为需要满足三个基本特性:碰撞稳固性,原根稳固性和第二原根稳固性。
    即:
    ●对于任何一个给定的消息,它都很容易就能运算出散列数值。
    ●难以由一个已知的散列数值,去推算出原始的消息。
    ●在不更动散列数值的前提下,修改消息内容是不可行的。
    ●对于两个不同的消息,它不能给与相同的散列数值。

    2005年,Wang等人给出了MD5算法和SHA-1算法的碰撞攻击方法,现今被广泛应用的MD5算法和SHA-1算法不再是安全的算法。
    SM3密码摘要算法是中国国家密码管理局2010年公布的中国商用密码杂凑算法标准。SM3算法适用于商用密码应用中的数字签名和验证,是在SHA-256基础上改进实现的一种算法。SM3算法采用Merkle-Damgard结构,消息分组长度为512位,摘要值长度为256位。现今为止,SM3算法的安全性相对较高。

    (3) 效率不同
    MD5、SHA1、SH2-256与SM3的对比:
    在这里插入图片描述
    2. SM3算法如何保证其安全性?
    SM3算法也是一种哈希算法,是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。
    1、算法的本质
    给数据加一个固定长度的指纹,这个固定长度就是256比特。
    2、处理过程
    第一步:填充,使填充后的数据的长度是512的整数倍
    先在数据的最尾巴上加一个1;然后把原始数据的长度用64比特表示,放在最后面;再看看现在的数据的长度值离512的整数还差多少个,差多少个就填多少个0在加的这个1和64比特的长度之间。
    第二步:分组
    把填充后的信息按照512比特一个分组进行分组,如果分成了N组,就是b(0),b(1),b(N-1)
    第三步:迭代压缩得到最后的杂凑值(哈希值)
    IV(n)=CF(IV(n-1),b(n-1))
    如果信息分为N组,那么IV(N)就是最后得到的杂凑值。

    展开全文
  • SM3算法的C++实现(代码)

    千次阅读 2021-11-26 10:49:14
    文章目录一、SM3算法原理二、SM3算法的C++代码实现三、SM3算法的实现结果(给了文档里两个示例的运行结果)1.当输入数据值“abc”时候的实验结果:2.当输入数据值为...


    一、SM3算法原理

    1. SM3密码杂凑算法文档
    2. 文档中对于SM3密码杂凑算法描述得十分清楚。整个算法主要涉及了两个主要的函数:填充函数、迭代压缩函数。
    3. 迭代压缩函数包括两部分的内容:消息扩展函数、压缩函数。
    4. 消息扩展函数涉及到的主要函数为:循环左移函数、异或操作函数、置换函数P1。
    5. 压缩函数涉及到的主要函数为:循环左移函数、模加运算函数、异或操作函数、布尔函数FFj、布尔函数GGj、置换函数P0。
    6. 输入的消息首先转换成为ASCII码;然后进行消息填充,使得其长度为512比特的倍数;其次经过迭代压缩最后输出哈希值结果。
      粗糙版流程图

    二、SM3算法的C++代码实现

    #include <iostream>
    #include <string>
    #include <cmath>
    using namespace std;
    
    //二进制转换为十六进制函数实现
    string BinToHex(string str) {
    	string hex = "";//用来存储最后生成的十六进制数
    	int temp = 0;//用来存储每次四位二进制数的十进制值
    	while (str.size() % 4 != 0) {//因为每四位二进制数就能够成为一个十六进制数,所以将二进制数长度转换为4的倍数
    		str = "0" + str;//最高位添0直到长度为4的倍数即可
    	}
    	for (int i = 0; i < str.size(); i += 4) {
    		temp = (str[i] - '0') * 8 + (str[i + 1] - '0') * 4 + (str[i + 2] - '0') * 2 + (str[i + 3] - '0') * 1;//判断出4位二进制数的十进制大小为多少
    		if (temp < 10) {//当得到的值小于10时,可以直接用0-9来代替
    			hex += to_string(temp);
    		}
    		else {//当得到的值大于10时,需要进行A-F的转换
    			hex += 'A' + (temp - 10);
    		}
    	}
    	return hex;
    }
    
    //十六进制转换为二进制函数实现
    string HexToBin(string str) {
    	string bin = "";
    	string table[16] = { "0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111" };
    	for (int i = 0; i < str.size(); i++) {
    		if (str[i] >= 'A'&&str[i] <= 'F') {
    			bin += table[str[i] - 'A' + 10];
    		}
    		else {
    			bin += table[str[i] - '0'];
    		}
    	}
    	return bin;
    }
    
    //二进制转换为十进制的函数实现
    int BinToDec(string str) {
    	int dec = 0;
    	for (int i = 0; i < str.size(); i++) {
    		dec += (str[i] - '0')*pow(2, str.size() - i - 1);
    	}
    	return dec;
    }
    
    //十进制转换为二进制的函数实现
    string DecToBin(int str) {
    	string bin = "";
    	while (str >= 1) {
    		bin = to_string(str % 2) + bin;
    		str = str / 2;
    	}
    	return bin;
    }
    
    //十六进制转换为十进制的函数实现
    int HexToDec(string str) {
    	int dec = 0;
    	for (int i = 0; i < str.size(); i++) {
    		if (str[i] >= 'A'&&str[i] <= 'F') {
    			dec += (str[i] - 'A' + 10)*pow(16, str.size() - i - 1);
    		}
    		else {
    			dec += (str[i] - '0')*pow(16, str.size() - i - 1);
    		}
    	}
    	return dec;
    }
    
    //十进制转换为十六进制的函数实现
    string DecToHex(int str) {
    	string hex = "";
    	int temp = 0;
    	while (str >= 1) {
    		temp = str % 16;
    		if (temp < 10 && temp >= 0) {
    			hex = to_string(temp) + hex;
    		}
    		else {
    			hex += ('A' + (temp - 10));
    		}
    		str = str / 16;
    	}
    	return hex;
    }
    
    string padding(string str) {//对数据进行填充 
    	string res = "";
    	for (int i = 0; i < str.size(); i++) {//首先将输入值转换为16进制字符串
    		res += DecToHex((int)str[i]);
    	}
    	cout << "输入字符串的ASCII码表示为:" << endl;
    	for (int i = 0; i < res.size(); i++) {
    		cout << res[i];
    		if ((i + 1) % 8 == 0) {
    			cout << "  ";
    		}
    		if ((i + 1) % 64 == 0 || (i + 1) == res.size()) {
    			cout << endl;
    		}
    	}
    	cout << endl;
    	int res_length = res.size() * 4;//记录的长度为2进制下的长度
    	res += "8";//在获得的数据后面添1,在16进制下相当于是添加8
    	while (res.size() % 128 != 112) {
    		res += "0";//“0”数据填充
    	}
    	string res_len = DecToHex(res_length);//用于记录数据长度的字符串
    	while (res_len.size() != 16) {
    		res_len = "0" + res_len;
    	}
    	res += res_len;
    	return res;
    }
    
    string LeftShift(string str, int len) {//实现循环左移len位功能
    	string res = HexToBin(str);
    	res = res.substr(len) + res.substr(0, len);
    	return BinToHex(res);
    }
    
    string XOR(string str1, string str2) {//实现异或操作
    	string res1 = HexToBin(str1);
    	string res2 = HexToBin(str2);
    	string res = "";
    	for (int i = 0; i < res1.size(); i++) {
    		if (res1[i] == res2[i]) {
    			res += "0";
    		}
    		else {
    			res += "1";
    		}
    	}
    	return BinToHex(res);
    }
    
    string AND(string str1, string str2) {//实现与操作
    	string res1 = HexToBin(str1);
    	string res2 = HexToBin(str2);
    	string res = "";
    	for (int i = 0; i < res1.size(); i++) {
    		if (res1[i] == '1' && res2[i] == '1') {
    			res += "1";
    		}
    		else {
    			res += "0";
    		}
    	}
    	return BinToHex(res);
    }
    
    string OR(string str1, string str2) {//实现或操作
    	string res1 = HexToBin(str1);
    	string res2 = HexToBin(str2);
    	string res = "";
    	for (int i = 0; i < res1.size(); i++) {
    		if (res1[i] == '0' && res2[i] == '0') {
    			res += "0";
    		}
    		else {
    			res += "1";
    		}
    	}
    	return BinToHex(res);
    }
    
    string NOT(string str) {//实现非操作
    	string res1 = HexToBin(str);
    	string res = "";
    	for (int i = 0; i < res1.size(); i++) {
    		if (res1[i] == '0') {
    			res += "1";
    		}
    		else {
    			res += "0";
    		}
    	}
    	return BinToHex(res);
    }
    
    char binXor (char str1, char str2) {//实现单比特的异或操作
    	return str1 == str2 ? '0' : '1';
    }
    
    char binAnd(char str1, char str2) {//实现单比特的与操作
    	return (str1 == '1'&&str2 == '1') ? '1' : '0';
    }
    
    string ModAdd(string str1, string str2) {//mod 2^32运算的函数实现
    	string res1 = HexToBin(str1);
    	string res2 = HexToBin(str2);
    	char temp = '0';
    	string res = "";
    	for (int i = res1.size() - 1; i >= 0; i--) {
    		res = binXor(binXor(res1[i], res2[i]), temp) + res;
    		if (binAnd(res1[i], res2[i]) == '1') {
    			temp = '1';
    		}
    		else {
    			if (binXor(res1[i], res2[i]) == '1') {
    				temp = binAnd('1', temp);
    			}
    			else {
    				temp = '0';
    			}
    		}
    	}
    	return BinToHex(res);
    }
    
    string P1(string str) {//实现置换功能P1(X)
    	return XOR(XOR(str, LeftShift(str, 15)), LeftShift(str, 23));
    }
    
    string P0(string str) {//实现置换功能P0(X)
    	return XOR(XOR(str, LeftShift(str, 9)), LeftShift(str, 17));
    }
    
    string T(int j) {//返回Tj常量值的函数实现
    	if (0 <= j && j <= 15) {
    		return "79CC4519";
    	}
    	else {
    		return "7A879D8A";
    	}
    }
    
    string FF(string str1, string str2, string str3, int j) {//实现布尔函数FF功能
    	if (0 <= j && j <= 15) {
    		return XOR(XOR(str1, str2), str3);
    	}
    	else {
    		return OR(OR(AND(str1, str2), AND(str1, str3)), AND(str2, str3));
    	}
    }
    
    string GG(string str1, string str2, string str3, int j) {//实现布尔函数GG功能
    	if (0 <= j && j <= 15) {
    		return XOR(XOR(str1, str2), str3);
    	}
    	else {
    		return OR(AND(str1, str2), AND(NOT(str1), str3));
    	}
    }
    string extension(string str) {//消息扩展函数
    	string res = str;//字符串类型存储前68位存储扩展字W值
    	for (int i = 16; i < 68; i++) {//根据公式生成第17位到第68位的W值
    		res += XOR(XOR(P1(XOR(XOR(res.substr((i-16)*8,8), res.substr((i - 9) * 8, 8)), LeftShift(res.substr((i - 3) * 8, 8), 15))), LeftShift(res.substr((i - 13) * 8, 8), 7)), res.substr((i - 6) * 8, 8));
    	}
    	cout << "扩展后的消息:" << endl;
    	cout << "W0,W1,……,W67的消息:" << endl;
    	for (int i = 0; i < 8; i++) {
    		for (int j = 0; j < 8; j++) {
    			cout << res.substr(i * 64 + j * 8, 8) << "  ";
    		}
    		cout << endl;
    	}
    	cout << res.substr(512, 8) << "  " << res.substr(520, 8) << "  " << res.substr(528, 8) << "  " << res.substr(536, 8) << endl;
    	cout << endl;
    	for (int i = 0; i < 64; i++) {//根据公式生成64位W'值
    		res += XOR(res.substr(i * 8, 8), res.substr((i + 4) * 8, 8));
    	}
    	cout << "W0',W1',……,W63'的消息:" << endl;
    	for (int i = 0; i < 8; i++) {
    		for (int j = 0; j < 8; j++) {
    			cout << res.substr(544+i * 64 + j * 8, 8) << "  ";
    		}
    		cout << endl;
    	}
    	cout << endl;
    	return res;
    }
    
    string compress(string str1, string str2) {//消息压缩函数
    	string IV = str2;
    	string A = IV.substr(0, 8), B = IV.substr(8, 8), C = IV.substr(16, 8), D = IV.substr(24, 8), E = IV.substr(32, 8), F = IV.substr(40, 8), G = IV.substr(48, 8), H = IV.substr(56, 8);
    	string SS1 = "", SS2 = "", TT1 = "", TT2 = "";
    	cout << "迭代压缩中间值: " << endl;
    	cout << "    A         B         C         D         E         F        G         H " << endl;
    	cout << A << "  " << B << "  " << C << "  " << D << "  " << E << "  " << F << "  " << G << "  " << H << endl;
    	for (int j = 0; j < 64; j++) {
    		SS1 = LeftShift(ModAdd(ModAdd(LeftShift(A, 12), E), LeftShift(T(j), (j%32))), 7);
    		SS2 = XOR(SS1, LeftShift(A, 12));
    		TT1 = ModAdd(ModAdd(ModAdd(FF(A, B, C, j), D), SS2), str1.substr((j + 68) * 8, 8));
    		TT2 = ModAdd(ModAdd(ModAdd(GG(E, F, G, j), H), SS1), str1.substr(j * 8, 8));
    		D = C;
    		C = LeftShift(B, 9);
    		B = A;
    		A = TT1;
    		H = G;
    		G = LeftShift(F, 19);
    		F = E;
    		E = P0(TT2);
    		cout << A << "  " << B << "  " << C << "  " << D << "  " << E << "  " << F << "  " << G << "  " << H << endl;
    	}
    	string res = (A + B + C + D + E + F + G + H);
    	cout << endl;
    	return res;
    }
    
    string iteration(string str) {//迭代压缩函数实现
    	int num = str.size() / 128;
    	cout << "消息经过填充之后共有 " + to_string(num) + " 个消息分组。" << endl;
    	cout << endl;
    	string V = "7380166F4914B2B9172442D7DA8A0600A96F30BC163138AAE38DEE4DB0FB0E4E";
    	string B = "", extensionB = "", compressB = "";
    	for (int i = 0; i < num; i++) {
    		cout << "第 " << to_string(i+1) << " 个消息分组:" << endl;
    		cout << endl;
    		B = str.substr(i * 128, 128);
    		extensionB = extension(B);
    		compressB = compress(extensionB, V);
    		V = XOR(V, compressB);
    	}
    	return V;
    }
    
    int main() {//主函数
    	string str[2];
    	str[0] = "abc";
    	str[1] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
    	for (int num = 0; num < 2; num++) {
    		cout << "示例 " + to_string(num + 1) + " :输入消息为字符串: " + str[num] << endl;
    		cout << endl;
    		string paddingValue = padding(str[num]);
    		cout << "填充后的消息为:" << endl;
    		for (int i = 0; i < paddingValue.size() / 64; i++) {
    			for (int j = 0; j < 8; j++) {
    				cout << paddingValue.substr(i * 64 + j * 8, 8) << "  ";
    			}
    			cout << endl;
    		}
    		cout << endl;
    		string result = iteration(paddingValue);
    		cout << "杂凑值:" << endl;
    		for (int i = 0; i < 8; i++) {
    			cout << result.substr(i * 8, 8) << "  ";
    		}
    		cout << endl;
    		cout << endl;
    	}
    }
    
    

    三、SM3算法的实现结果(给了文档里两个示例的运行结果)

    1.当输入数据值“abc”时候的实验结果:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.当输入数据值为“abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd”时候的实验结果:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    总结

    • 实现的C++代码还有很多值得改进的地方,但是因为本人是菜鸟一只,代码写的略长,哈哈哈。
    展开全文
  • SM2SM3算法的python实现,完全按照国密标准实现,所用参数都按照国密标准来的,可以实现签名及认证功能,以及杂凑功能
  • sm3标准算法

    2018-08-17 15:56:25
    在linux平台上用c++实现哈希算法,并进行相关测试,该方法简单易实施。
  • SM3算法 C语言 (从OpenSSL库中分离算法:六) OpenSSL简介: OpenSSL 是用于传输层安全性 (TLS) 和安全套接字层 (SSL) 协议的一个强大、商业级和功能齐全的工具包,它也是一个通用的密码学库。包含有RSA、SM4、DES、...

    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相当。

    移植过程

    一、下载代码

    从OpenSSL的Github仓库下载代码,可以下载master分支,也可以下载最新的release版本。将下载的文件解压,得到代码。

    重点关注红框目录:

    • crypto目录内是各种加密算法
    • include目录内是各加密算法对外接口的头文件

    在这里插入图片描述

    二、准备环境

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

    在这里插入图片描述
    在这里插入图片描述

    三、准备文件

    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文件夹内文件如下:

    在这里插入图片描述
    删除目录内的如下本项目中无用文件:

    • 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 <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 };
    
        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));
        }
    }
    

    修改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
    

    修改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
    
    

    修改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;
        }
    }
    

    修改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结果如下:

    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计算

    欢迎大家关注、留言讨论、可分享源码

    展开全文
  • SM2/SM3算法C语言实现

    2018-06-06 20:07:24
    1、完整的SM2/SM3算法,C语言实现,可用于扫码POS安全认证; 2、SM2加密/解密、SM2签名/验签 3、内含测试程序,在Linux环境下进入目录后make即可编译,已经在ubuntu16.04环境下编译测试OK; 4、已经在银行卡检测中心...
  • 提供国密三方API,代码可以运行,提供了SM2,SM3SM4标准算法,欢迎大家下载
  • SM3算法IP核

    2019-01-09 16:51:45
    基于verilog硬件描述语言设计的SM3算法IP核,通过vivado进行设计并调试通过,提供一个C语言的调用接口
  • PHP实现国密SM3算法

    千次阅读 2021-09-15 15:53:28
    最近对接一个第三方系统,对方要求接口签名加密使用sm3加密算法,不过php没有原生支持该算法的函数,所以需要借助外力了。网上查资料发现在PHP中实现sm3算法,大概有一下三种途径:A.使用PHP的OpenSSL扩展实现 B.使用一...
  • 国密算法SM3的C++实现,封装成DLL。再用VB调用DLL进行字符串加密、字节数组加密、文件加密的示例。其它语言同理可用。
  • SM2和SM3算法

    2018-09-26 17:11:41
    sm2和SM3算法,国密 SM2 SM3 签名 验签 加解密 公私钥。经测试,很OK
  • SM3算法 (python)

    2022-03-18 16:59:23
    国密SM3 python源码
  • 通过SM3算法杂凑用户原始密钥形成新的密钥,将新密钥作为SM4加密算法的密钥。 系统采用Spring MVC开发,其中使用了artery(封装了spring),兼容spring。
  • SM3算法原理解析

    千次阅读 2021-08-13 18:00:21
    SM3算法原理解析 (1)消息填充 首先将比特“1’ 添加到消息的末尾,再添加k个零,这里k是方程l+1+k = 448 mod 512的最小的非负解。然后再添加一个64比特长的块,其值等于消息M的长度l的二进制表示,使得填充后的消息...
  • 在分析SM3算法的基础上详细介绍了目前Hash函数的4种硬件实现策略,同时给出了迭代方式和基于充分利用时钟周期的循环展开方式下的FPGA实现。该循环展开方式有效地减少了一半的工作时钟数和11%的运算时间,吞吐量提高...
  • sm3算法

    千次阅读 2017-09-30 09:59:44
    sm3算法c语言实现 /*    2017.9.24 am 10:00 -11:50  2017.9.24 pm 14:00-17:00 19:00-23:00  2017.9.25 pm 14:00-17:30 */ #include #include #include unsigned int w0[70],w1[70];//用于压缩...
  • 基于FPGA的SM3算法快速实现方案
  • 国密SM3算法python2, python3实现,原有为python2版本,更新增加python3版本
  • 国密SM3算法

    2019-07-17 16:30:14
    国密SM3算法,芯片中有sm3函数的入口,每次只能输入8个字节(64位)的16进制数,所以要把文件拆分成N*8字节,并转为16进制,需要执行sm3函数N次 前面N-1次和最后一次执行函数所用的报文不同,前面N-1次中报文的p1=01...
  • 国密SM3算法的Java实现,可以与bc很好的结合,实现国密算法扩展。已经用SM3算法标准中的示例数据进行验证,两组示例数据对比测试完全正确。 附带工具类实现方式,费了两天的时候搞出来的,100%对比正确.
  • 国密SM3算法,基于Verilog实现,亲测可用,且性能优良,2Gbps 国密SM3算法,基于Verilog实现,亲测可用,且性能优良,2Gbps
  • 国密标准SM3算法,java实现

    千次阅读 2021-03-14 00:42:06
    SM3算法对标国际标准MD5和SHA1算法算法更安全下面直接上代码:/*** SM3杂凑算法* @author Administrator**/public class SM3 {//hash值byte长度private static final int HASH_LENGTH_BYTE = 32;//hash值WORD长度...
  • 按照国密文档通过Java实现SM2密码算法加密、签名验签,SM3密码杂凑算法 经过详尽的测试过后没有发现问题,但建议大家在使用时仍进行验证。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,719
精华内容 10,287
关键字:

sm3算法