赞
踩
结合官方文档对sm3算法研究了一下,从GMSSL源码挖出sm3,处理一下word数据存储方式后调试通过
#include <string.h> #include <stdio.h> #include <stdlib.h> #include "sm3.h" //大小端数据转换函数,例:0x00112233转换为0x33221100 uint32_t Lendian_2_Bendian(uint32_t value) { return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |(value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; } void sm3_init(sm3_ctx_t *ctx) { //初始值IV ctx->digest[0] = 0x7380166F; ctx->digest[1] = 0x4914B2B9; ctx->digest[2] = 0x172442D7; ctx->digest[3] = 0xDA8A0600; ctx->digest[4] = 0xA96F30BC; ctx->digest[5] = 0x163138AA; ctx->digest[6] = 0xE38DEE4D; ctx->digest[7] = 0xB0FB0E4E; ctx->nblocks = 0; ctx->num = 0; } //前n-1个512bit块数据处理 void sm3_update(sm3_ctx_t *ctx, const unsigned char* data, size_t data_len) { if (ctx->num) { unsigned int left = SM3_BLOCK_SIZE - ctx->num; if (data_len < left) { memcpy(ctx->block + ctx->num, data, data_len); ctx->num += data_len; return; } else { memcpy(ctx->block + ctx->num, data, left); sm3_compress(ctx->digest, ctx->block); ctx->nblocks++; data += left; data_len -= left; } } //迭代压缩(处理前n-1个512bit块数据) while(data_len >= SM3_BLOCK_SIZE) { sm3_compress(ctx->digest, data); ctx->nblocks++; data += SM3_BLOCK_SIZE; data_len -= SM3_BLOCK_SIZE; } //剩下一组不足512bit的块数据,进行单独处理 ctx->num = data_len; if(data_len) { memcpy(ctx->block, data, data_len); } } /************************************************************************ * 函数功能:处理剩余的一组不足512bit的块数据,并输出最终摘要值 * 输入: * @*ctx :输入数据 * 输出: * @*digest :摘要值 *返回值:NULL ************************************************************************/ void sm3_final(sm3_ctx_t *ctx, unsigned char *digest) { int i; uint32_t *pdigest = (uint32_t *)digest; uint32_t *count = (uint32_t *)(ctx->block + SM3_BLOCK_SIZE - 8); /***** 数据填充 **********/ //首先在数据末尾填充“1” ctx->block[ctx->num] = 0x80; //进行“0”填充,根据剩余需要填充数据的长度是否有64bit的空间来决定填充“0”的个数 if (ctx->num + 9 <= SM3_BLOCK_SIZE) { memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 9); } else { memset(ctx->block + ctx->num + 1, 0, SM3_BLOCK_SIZE - ctx->num - 1); sm3_compress(ctx->digest, ctx->block); memset(ctx->block, 0, SM3_BLOCK_SIZE - 8); } //最后64bit填充数据长度的二进制表示(word型数据需要以大端进行存储) count[0] = cpu_to_be32((ctx->nblocks) >> 23); count[1] = Lendian_2_Bendian(cpu_to_be32((ctx->nblocks << 9) + (ctx->num << 3)));//本系统用小端模式需要转换 sm3_compress(ctx->digest, ctx->block); for (i = 0; i < sizeof(ctx->digest)/sizeof(ctx->digest[0]); i++) { pdigest[i] =Lendian_2_Bendian(cpu_to_be32(ctx->digest[i])); } } #define ROTATELEFT(X,n) (((X)<<(n)) | ((X)>>(32-(n)))) #define P0(x) ((x) ^ ROTATELEFT((x),9) ^ ROTATELEFT((x),17)) #define P1(x) ((x) ^ ROTATELEFT((x),15) ^ ROTATELEFT((x),23)) #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)) ) /************************************************************************ * 函数功能:压缩函数CF * 输入: * @*digest :256bit初始数据(IV) * @*block :经过填充后的数据(512bit对齐) * 输出: * @*digest :迭代压缩结果 *返回值:NULL ************************************************************************/ void sm3_compress(uint32_t digest[8], const unsigned char block[64]) { int j; uint32_t W[68], W1[64]; const uint32_t *pblock = (const uint32_t *)block; uint32_t A = digest[0]; uint32_t B = digest[1]; uint32_t C = digest[2]; uint32_t D = digest[3]; uint32_t E = digest[4]; uint32_t F = digest[5]; uint32_t G = digest[6]; uint32_t H = digest[7]; uint32_t SS1,SS2,TT1,TT2,T[64]; /***** 消息扩展 *******/ //W0 W1...W67 for(j = 0; j < 16; j++) { //word数据以大端存储,后续计算基于该组数据,无需在进行大小端转换 W[j] = Lendian_2_Bendian(cpu_to_be32(pblock[j])); } for(j = 16; j < 68; j++) { W[j] = P1( W[j-16] ^ W[j-9] ^ ROTATELEFT(W[j-3],15)) ^ ROTATELEFT(W[j - 13],7 ) ^ W[j-6]; } //W'0 W'1 ... W'63 for( j = 0; j < 64; j++) { W1[j] = W[j] ^ W[j+4]; } //压缩函数 for(j =0; j < 16; j++) { T[j] = 0x79CC4519; SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7); SS2 = SS1 ^ ROTATELEFT(A,12); TT1 = FF0(A,B,C) + D + SS2 + W1[j]; TT2 = GG0(E,F,G) + H + SS1 + W[j]; D = C; C = ROTATELEFT(B,9); B = A; A = TT1; H = G; G = ROTATELEFT(F,19); F = E; E = P0(TT2); } for(j =16; j < 64; j++) { T[j] = 0x7A879D8A; SS1 = ROTATELEFT((ROTATELEFT(A,12) + E + ROTATELEFT(T[j],j)), 7); SS2 = SS1 ^ ROTATELEFT(A,12); TT1 = FF1(A,B,C) + D + SS2 + W1[j]; TT2 = GG1(E,F,G) + H + SS1 + W[j]; D = C; C = ROTATELEFT(B,9); B = A; A = TT1; H = G; G = ROTATELEFT(F,19); F = E; E = P0(TT2); } digest[0] ^= A; digest[1] ^= B; digest[2] ^= C; digest[3] ^= D; digest[4] ^= E; digest[5] ^= F; digest[6] ^= G; digest[7] ^= H; } /************************************************************************ * 函数功能:sm3接口函数 * 输入: * @*msg :输入消息 * @*msglen :消息长度 * 输出: * @*dgst :摘要值(256bit对齐) *返回值:NULL ************************************************************************/ void sm3(const unsigned char *msg, size_t msglen, unsigned char dgst[SM3_DIGEST_LENGTH]) { sm3_ctx_t ctx; sm3_init(&ctx); sm3_update(&ctx, msg, msglen); sm3_final(&ctx, dgst); memset(&ctx, 0, sizeof(sm3_ctx_t)); } void main(void) { int i = 0; unsigned char msg1[] = "abc"; unsigned char msg[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"; unsigned char dgst[32] = ""; printf("\nmassage : %s\n",msg1); sm3(msg1,strlen(msg1),dgst); printf("\ndigest : "); for(i=0; i<sizeof(dgst); i++) { printf("%02x",dgst[i]); if((i+1) % 4 == 0) { printf(" "); } } printf("\n\n"); printf("\nmassage : %s\n",msg); sm3(msg,strlen(msg),dgst); printf("\ndigest : "); for(i=0; i<sizeof(dgst); i++) { printf("%02x",dgst[i]); if((i+1) % 4 == 0) { printf(" "); } } printf("\n\n"); }
测试结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。