1. /*
  2. * sm3.h
  3. *
  4. * 为使此算法兼容32位、64位下Linux或Windows系统,
  5. * 选择 int 来表示 32 位整数。
  6. * 消息长度最大限定为 2**32 - 1(单位:比特),
  7. * 且为 8 的倍数(消息的最小单元为字节)。
  8. */
  9. #ifndef _SM3_H_
  10. #define _SM3_H_
  11.  
  12. /*
  13. * SM3算法产生的哈希值大小(单位:字节)
  14. */
  15. #define SM3_HASH_SIZE 32
  16.  
  17. /*
  18. * SM3上下文
  19. */
  20. typedef struct SM3Context
  21. {
  22. unsigned int intermediateHash[SM3_HASH_SIZE / ];
  23. unsigned char messageBlock[];
  24. } SM3Context;
  25.  
  26. /*
  27. * SM3计算函数
  28. */
  29. unsigned char *SM3Calc(const unsigned char *message,
  30. unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);
  31.  
  32. #endif // _SM3_H_
  1. /*
  2. * sm3.c
  3. */
  4. #include <stdio.h>
  5. #include <memory.h>
  6. #include "sm3.h"
  7.  
  8. /*
  9. * 判断运行环境是否为小端
  10. */
  11. static const int endianTest = ;
  12. #define IsLittleEndian() (*(char *)&endianTest == 1)
  13.  
  14. /*
  15. * 向左循环移位
  16. */
  17. #define LeftRotate(word, bits) ( (word) << (bits) | (word) >> (32 - (bits)) )
  18.  
  19. /*
  20. * 反转四字节整型字节序
  21. */
  22. unsigned int *ReverseWord(unsigned int *word)
  23. {
  24. unsigned char *byte, temp;
  25.  
  26. byte = (unsigned char *)word;
  27. temp = byte[];
  28. byte[] = byte[];
  29. byte[] = temp;
  30.  
  31. temp = byte[];
  32. byte[] = byte[];
  33. byte[] = temp;
  34. return word;
  35. }
  36.  
  37. /*
  38. * T
  39. */
  40. unsigned int T(int i)
  41. {
  42. if (i >= && i <= )
  43. return 0x79CC4519;
  44. else if (i >= && i <= )
  45. return 0x7A879D8A;
  46. else
  47. return ;
  48. }
  49.  
  50. /*
  51. * FF
  52. */
  53. unsigned int FF(unsigned int X, unsigned int Y, unsigned int Z, int i)
  54. {
  55. if (i >= && i <= )
  56. return X ^ Y ^ Z;
  57. else if (i >= && i <= )
  58. return (X & Y) | (X & Z) | (Y & Z);
  59. else
  60. return ;
  61. }
  62.  
  63. /*
  64. * GG
  65. */
  66. unsigned int GG(unsigned int X, unsigned int Y, unsigned int Z, int i)
  67. {
  68. if (i >= && i <= )
  69. return X ^ Y ^ Z;
  70. else if (i >= && i <= )
  71. return (X & Y) | (~X & Z);
  72. else
  73. return ;
  74. }
  75.  
  76. /*
  77. * P0
  78. */
  79. unsigned int P0(unsigned int X)
  80. {
  81. return X ^ LeftRotate(X, ) ^ LeftRotate(X, );
  82. }
  83.  
  84. /*
  85. * P1
  86. */
  87. unsigned int P1(unsigned int X)
  88. {
  89. return X ^ LeftRotate(X, ) ^ LeftRotate(X, );
  90. }
  91.  
  92. /*
  93. * 初始化函数
  94. */
  95. void SM3Init(SM3Context *context)
  96. {
  97. context->intermediateHash[] = 0x7380166F;
  98. context->intermediateHash[] = 0x4914B2B9;
  99. context->intermediateHash[] = 0x172442D7;
  100. context->intermediateHash[] = 0xDA8A0600;
  101. context->intermediateHash[] = 0xA96F30BC;
  102. context->intermediateHash[] = 0x163138AA;
  103. context->intermediateHash[] = 0xE38DEE4D;
  104. context->intermediateHash[] = 0xB0FB0E4E;
  105. }
  106.  
  107. /*
  108. * 处理消息块
  109. */
  110. void SM3ProcessMessageBlock(SM3Context *context)
  111. {
  112. int i;
  113. unsigned int W[];
  114. unsigned int W_[];
  115. unsigned int A, B, C, D, E, F, G, H, SS1, SS2, TT1, TT2;
  116.  
  117. /* 消息扩展 */
  118. for (i = ; i < ; i++)
  119. {
  120. W[i] = *(unsigned int *)(context->messageBlock + i * );
  121. if (IsLittleEndian())
  122. ReverseWord(W + i);
  123. //printf("%d: %x\n", i, W[i]);
  124. }
  125. for (i = ; i < ; i++)
  126. {
  127. W[i] = P1(W[i - ] ^ W[i - ] ^ LeftRotate(W[i - ], ))
  128. ^ LeftRotate(W[i - ], )
  129. ^ W[i - ];
  130. //printf("%d: %x\n", i, W[i]);
  131. }
  132. for (i = ; i < ; i++)
  133. {
  134. W_[i] = W[i] ^ W[i + ];
  135. //printf("%d: %x\n", i, W_[i]);
  136. }
  137.  
  138. /* 消息压缩 */
  139. A = context->intermediateHash[];
  140. B = context->intermediateHash[];
  141. C = context->intermediateHash[];
  142. D = context->intermediateHash[];
  143. E = context->intermediateHash[];
  144. F = context->intermediateHash[];
  145. G = context->intermediateHash[];
  146. H = context->intermediateHash[];
  147. for (i = ; i < ; i++)
  148. {
  149. SS1 = LeftRotate((LeftRotate(A, ) + E + LeftRotate(T(i), i)), );
  150. SS2 = SS1 ^ LeftRotate(A, );
  151. TT1 = FF(A, B, C, i) + D + SS2 + W_[i];
  152. TT2 = GG(E, F, G, i) + H + SS1 + W[i];
  153. D = C;
  154. C = LeftRotate(B, );
  155. B = A;
  156. A = TT1;
  157. H = G;
  158. G = LeftRotate(F, );
  159. F = E;
  160. E = P0(TT2);
  161. }
  162. context->intermediateHash[] ^= A;
  163. context->intermediateHash[] ^= B;
  164. context->intermediateHash[] ^= C;
  165. context->intermediateHash[] ^= D;
  166. context->intermediateHash[] ^= E;
  167. context->intermediateHash[] ^= F;
  168. context->intermediateHash[] ^= G;
  169. context->intermediateHash[] ^= H;
  170. }
  171.  
  172. /*
  173. * SM3算法主函数
  174. */
  175. unsigned char *SM3Calc(const unsigned char *message,
  176. unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE])
  177. {
  178. SM3Context context;
  179. unsigned int i, remainder, bitLen;
  180.  
  181. /* 初始化上下文 */
  182. SM3Init(&context);
  183.  
  184. /* 对前面的消息分组进行处理 */
  185. for (i = ; i < messageLen / ; i++)
  186. {
  187. memcpy(context.messageBlock, message + i * , );
  188. SM3ProcessMessageBlock(&context);
  189. }
  190.  
  191. /* 填充消息分组,并处理 */
  192. bitLen = messageLen * ;
  193. if (IsLittleEndian())
  194. ReverseWord(&bitLen);
  195. remainder = messageLen % ;
  196. memcpy(context.messageBlock, message + i * , remainder);
  197. context.messageBlock[remainder] = 0x80;
  198. if (remainder <= )
  199. {
  200. /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
  201. * 故将高 4 个字节赋为 0 。*/
  202. memset(context.messageBlock + remainder + , , - remainder - - + );
  203. memcpy(context.messageBlock + - , &bitLen, );
  204. SM3ProcessMessageBlock(&context);
  205. }
  206. else
  207. {
  208. memset(context.messageBlock + remainder + , , - remainder - );
  209. SM3ProcessMessageBlock(&context);
  210. /* 长度按照大端法占8个字节,该程序只考虑长度在 2**32 - 1(单位:比特)以内的情况,
  211. * 故将高 4 个字节赋为 0 。*/
  212. memset(context.messageBlock, , - );
  213. memcpy(context.messageBlock + - , &bitLen, );
  214. SM3ProcessMessageBlock(&context);
  215. }
  216.  
  217. /* 返回结果 */
  218. if (IsLittleEndian())
  219. for (i = ; i < ; i++)
  220. ReverseWord(context.intermediateHash + i);
  221. memcpy(digest, context.intermediateHash, SM3_HASH_SIZE);
  222.  
  223. return digest;
  224. }

SM3算法的更多相关文章

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

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

  2. sm3算法的简单介绍

    转自:https://blog.csdn.net/hugewaves/article/details/53765063 SM3算法也是一种哈希算法,中国国家密码管理局在2010年发布,其名称是SM3密 ...

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

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

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

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

  5. 源代码方式向openssl中加入新算法完整具体步骤(演示样例:摘要算法SM3)【非engine方式】

    openssl简单介绍 openssl是一个功能丰富且自包括的开源安全工具箱.它提供的主要功能有:SSL协议实现(包括SSLv2.SSLv3和TLSv1).大量软算法(对称/非对称/摘要).大数运算. ...

  6. AES SHA-1 SM3 MD5

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

  7. 《基于Arm实验箱的国密算法应用》课程设计 结题报告

    <基于Arm实验箱的国密算法应用>课程设计 结题报告 小组成员姓名:20155206赵飞 20155220吴思其 20155234昝昕明 指导教师:娄嘉鹏 设计方案 题目要求:基于Arm实 ...

  8. java sm3加密算法

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

  9. Java国密相关算法(bouncycastle)

    公用类算法: PCIKeyPair.java /** * @Author: dzy * @Date: 2018/9/27 14:18 * @Describe: 公私钥对 */ @Data @AllAr ...

随机推荐

  1. typescript 接口的新认识

    interface 用于接收服务器的数据. eg: interface mmmmm { x: string, y: number, z: number, select: KnockoutObserva ...

  2. mysql日期函数 和sql语句扩展information_schema show processlist;

    SELECT NOW(); SELECT CURDATE(); SELECT YEAR(NOW()) SELECT CONCAT("mysqldump ","-uroot ...

  3. Web前端都学点儿啥?

    Web开发如今是如日中天,热的发烫.但是Web开发相关的技术和知识却像N座大山一样,耸立在我们面前,连绵起伏,漫无边际.那么这些山头那些我们应该占领,那些我们应该绕开,很多人看着就蒙了,这不光是初学者 ...

  4. POJ3694-Network(Tarjan缩点+LCA)

    题目链接 题意:给你一个连通图.然后再给你n个询问,每一个询问给一个点u,v表示加上u,v之后又多少个桥. 思路:用Tarjan缩点后,形成一棵树,所以树边都是桥了.然后增加边以后,查询LCA,LCA ...

  5. JAVA中BufferedReader设置编码的必要性

    实验环境 Myeclipse 默认编码 UTF-8 先看两种读文件的方式: 方式一: InputStreamReader fReader = new InputStreamReader(new Fil ...

  6. 怎样在asp.net中用一般处理文件ashx实现下载功能

    /// <summary> /// 下载文件,支持大文件.续传.速度限制.支持续传的响应头Accept-Ranges.ETag,请求头Range . /// Accept-Ranges:响 ...

  7. hdu 4681(枚举+dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4681 思路:首先预处理出串C在A,B中的所有的位置,然后从前向后求一次最长公共子序列,从后向前求一次最 ...

  8. 【BZOJ1976】[BeiJing2010组队]能量魔方 Cube 最小割

    [BZOJ1976][BeiJing2010组队]能量魔方 Cube Description 小C 有一个能量魔方,这个魔方可神奇了,只要按照特定方式,放入不同的 能量水晶,就可以产生巨大的能量. 能 ...

  9. C语言练习题

    C语言练习题 1. 以下选项中,合法的一组C语言数值常量是(     ) A)028  .5e-3  .0xf B)12.  OXa23   4.5e0 C).177   4e1.5  Oabc D) ...

  10. Architectural Styles and the Design of Network-based Software Architectures

    w Architectural Styles and the Design of Network-based Software Architectures  http://www.ics.uci.ed ...