2.7 SM3

sm3.h

  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. * SM3算法产生的哈希值大小(单位:字节)
  13. */
  14. #define SM3_HASH_SIZE 32
  15. /*
  16. * SM3上下文
  17. */
  18. typedef struct SM3Context
  19. {
  20. unsigned int intermediateHash[SM3_HASH_SIZE / 4];
  21. unsigned char messageBlock[64];
  22. } SM3Context;
  23. /*
  24. * SM3计算函数
  25. */
  26. unsigned char *SM3Calc(const unsigned char *message,
  27. unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);
  28. #endif // _SM3_H_

sm3.c

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

sm3Test.cpp

  1. // sm3Test.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include "sm3.h"
  7. #include <iostream>
  8. //#pragma comment(lib,"sm3dll2")
  9. //extern "C" void SM3Call(const unsigned char *message,unsigned int messageLen, unsigned char digest[SM3_HASH_SIZE]);
  10. int main( int argc, char *argv[] )
  11. {
  12. unsigned char input[256] = "12345678";
  13. int ilen = 3;
  14. unsigned char output[32];
  15. int i;
  16. // ctx;
  17. printf("Message:\n");
  18. printf("%s\n",input);
  19. SM3Calc(input, 8, output);
  20. printf("Hash:\n ");
  21. for(i=0; i<32; i++)
  22. {
  23. printf("%02x",output[i]);
  24. if (((i+1) % 4 ) == 0) printf(" ");
  25. }
  26. printf("\n");
  27. unsigned char input2[256] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd";
  28. int ilen2 = 64;
  29. unsigned char output2[32];
  30. int i2;
  31. // ctx;
  32. printf("Message:\n");
  33. printf("%s\n", input2);
  34. SM3Calc(input2, ilen2, output2);
  35. printf("Hash:\n ");
  36. for (i2 = 0; i2<32; i2++)
  37. {
  38. printf("%02x", output2[i2]);
  39. if (((i2 + 1) % 4) == 0) printf(" ");
  40. }
  41. printf("\n");
  42. system("pause");
  43. }