当前位置:   article > 正文

SM3 hash算法原理和硬件实现

sm3 hash

#声明:本文创作内容含代码均为个人创作所得,允许学习、传阅,不得用于商业用途#

#本文包含国密SM3从算法到硬件实现的全部# 

#读者务必认真理解代码实现过程,而不知简单的复制粘贴#

一 背景:

SM3是一种杂凑(hash)算法的计算方法,是国家密码公开算法标准,与国际上SHA-256相对应。其主要适用于商用密码应用中的数字签名和验证、消息认证码的生成与验证以及随机数的生成。

二:算法说明:

建议先直接下载“SM3密码杂凑算法”一文阅读

1. 简述

        对长度为L(L<2^64)比特的消息m,经过杂凑算法填充迭代压缩,生成一个256比特的数据。

2. 填充

填充的目的是为了保证消息比特长度(也就是0和1的总个数)是512的倍数,此举是为了满足后面迭代要求。首先将比特“1”,添加到消息的尾部,然后再添加K个比特“0”,然后再添加64个比特串,比特串是消息长度L的二进制表示,比如消息长度是24个比特,那么添加的64个比特串的二进制表示为 00…011000(十进制是24)。其中数字K满足一下等式,L+1+K+64  = 0mod 512, 也就是512的整数倍。

       

                                        上图是来源于国密pdf

3. 迭代

将上面填充后的消息按照每512比特进行分组,B0,B1,B2,… , B(n-1)

迭代方式:上一轮计算结果hash值和本轮的B(i)运算得到本轮的hash值, 用V来表示。伪代码如下:

V(0)是256比特的初始值,固定且已知,B(i)就是上面的填充分组后的消息,最终结果为V(n)

那么这个迭代压缩函数具体是怎样的形式呢?且往下看

3.1 消息扩展

      第一步:

也就是W0~W15就是分组消息的前16个字,然后用这16个字迭代出W16~W67,然后再用W0~W67迭代出W`0~W`63

3.2: 压缩函数CV

初始化常量IV = 7380166f 4914b2b9 172442d7 da8a0600 a96f30bc 163138aa e38dee4d b0fb0e4e,

由于编辑器打字不太方便,所以我就用截图的方式贴在这里:

说明:因为计算一组数据需要经过64次迭代,所以上面的循环变量为0~63,为了增加复杂度,在不同的迭代时间使用不同的变量或函数;

迭代过程:

迭代过程先用常量赋值给ABCDEFGH,经过64轮迭代,每轮迭代会更新中间变量TT1,TT2,SS1,SS2;64轮迭代结束后,ABCDEFGH的值就是本轮V的值,该值用于下一次迭代;

算法总结:将输入的数据先进行填充得到N个512比特的数据,然后经过N轮迭代压缩运算,每一轮的具体是先将输入的512比特划分为16个字,用这16个字经过运算获得一些中间变量值,然后用这些中间变量值以及上一次轮的hash值经过64轮的逻辑运算,就可以得到最终的hash值;

三 算法代码

因为python库和IDE比较完善,同时python也是目前很火的一种编程语言,所以我们采用python来实现。该代码均在Pycharm中实现

python是基于字符串来处理数据的,用python来进行数据位域计算是很恶心的,大家一定要注意闭坑啊,太坑了python。

不熟悉python的小伙伴一定要自己写一遍,否则这里的坑以后很难规避的

对于软件输入的数据格式有两种,一种是字符,比如‘abc’,另外一种是16进制

python代码如下:

  1. class SM3_PRE_PROCESS:
  2. def str2byte(self, string):
  3. hex_array = []
  4. string_encode = string.encode()
  5. for char in string:
  6. hex_array.append(int(ord(char)))
  7. return hex_array
  8. def num2byte(self, string):
  9. hex_array = []
  10. string_len = len(string)
  11. if (string_len % 2):
  12. string = '0' + string
  13. #string_encode = string.encode()
  14. for i in range(int(string_len / 2)):
  15. hex_array.append(int(string[i * 2:i * 2 + 2], 16))
  16. return hex_array
  17. def padding(self, string, num):
  18. if (num == 0):
  19. data = self.str2byte(string)
  20. bit_len = len(string) * 8 # each num is 8 bit
  21. else:
  22. data = self.num2byte(string)
  23. bit_len = len(data) * 8 # each num is 8 bit
  24. #bit_len = len(string) * 8 # each num is 8 bit
  25. string_0_len = 512 - (bit_len + 1 + 64) % 512
  26. string_0 = '1' + ('0' * string_0_len) # internal bin
  27. string_64_bit = '0' * (64 - (len(bin(bit_len)) - 2)) + bin(bit_len)[2:] # last 64bit
  28. padding_bit = string_0 + string_64_bit
  29. for i in range(int(len(padding_bit) / 8)): # message to 16 word(32bit)
  30. data.append(int(padding_bit[8 * i:8 * (i + 1)], 2))
  31. return data
  32. class SM3_CALCU:
  33. IV = '7380166f4914b2b9172442d7da8a0600a96f30bc163138aae38dee4db0fb0e4e'
  34. V0 = []
  35. for i in range(8):
  36. V0.append(
  37. (int(IV[8*i:8*(i+1)], 16)) & 0xFFFFFFFF) # transform each 8byte to int, so we can calculate with int
  38. def rotate_left(self,a,k):
  39. k = k % 32
  40. return ((a << k) & 0xFFFFFFFF) | ((a & 0xFFFFFFFF) >> (32-k))
  41. def T(self, i):
  42. if (i <= 15):
  43. return int('79cc4519', 16) & 0xFFFFFFFF
  44. else:
  45. return int('7a879d8a', 16) & 0xFFFFFFFF
  46. def FF(self, X, Y, Z, j):
  47. if 0 <= j <= 15:
  48. return X ^ Y ^ Z
  49. else:
  50. return (X & Y) | (X & Z) | (Y & Z)
  51. def GG(self, X, Y, Z, j):
  52. if 0 <= j <= 15:
  53. return X ^ Y ^ Z
  54. else:
  55. return (X & Y) | (~X & Z)
  56. def P0(self, X):
  57. return X ^ self.rotate_left(X,9) ^ self.rotate_left(X,17)
  58. def P1(self, X):
  59. return X ^ self.rotate_left(X,15) ^ self.rotate_left(X,23)
  60. def info_expand(self, info):
  61. ''' 16 word total 16*32= 512 bit namely 64 byte '''
  62. W = [0] * 68
  63. W_ = [0] * 64
  64. word_list = [0]*16
  65. for i in range(16):
  66. # tmp = (hex(info[4*i]))[2:] + hex(info[4*i+1])[2:] + hex(info[4*i+2])[2:] + hex(info[4*i+3])[2:] # big hole
  67. tmp = ('{:02x}'.format(info[4*i])) + ('{:02x}'.format(info[4*i+1])) + ('{:02x}'.format(info[4*i+2])) + ('{:02x}'.format(info[4*i+3]))
  68. word_list[i] = int(tmp,16) & 0xFFFFFFFF
  69. W[0:16] = word_list
  70. for j in range(16, 68):
  71. xx = (self.P1(W[j - 16] ^ W[j - 9] ^ (self.rotate_left(W[j - 3], 15)))) & 0xFFFFFFFF
  72. W[j] = (self.P1(W[j - 16] ^ W[j - 9] ^ self.rotate_left(W[j - 3] ,15)) ^ self.rotate_left(W[j - 13] , 7) ^ W[j - 6]) & 0xFFFFFFFF
  73. for j in range(64):
  74. W_[j] = W[j] ^ W[j + 4]
  75. return (W, W_)
  76. def iteration(self, msg, V):
  77. (W, W_) = self.info_expand(msg)
  78. A, B, C, D, E, F, G, H = V
  79. for j in range(64):
  80. SS1 = (self.rotate_left(self.rotate_left(A, 12) + E + self.rotate_left(self.T(j), j), 7)) & 0xFFFFFFFF
  81. SS2 = SS1 ^ self.rotate_left(A, 12)
  82. TT1 = (self.FF(A, B, C, j) + D + SS2 + W_[j]) & 0xFFFFFFFF
  83. TT2 = (self.GG(E, F, G, j) + H + SS1 + W[j]) & 0xFFFFFFFF
  84. D = C
  85. C = self.rotate_left(B ,9)
  86. B = A
  87. A = TT1
  88. H = G
  89. G = self.rotate_left(F , 19)
  90. F = E
  91. E = self.P0(TT2)
  92. return [A, B, C, D, E, F, G, H]
  93. def loop_cal(self, x):
  94. loop_len = int(len(x) / 64) # how much 512 bit
  95. V = [[0]] * (loop_len + 1)
  96. V[0] = self.V0
  97. for i in range(loop_len):
  98. [A, B, C, D, E, F, G, H] = self.iteration(x[64*i:64*(i+1)], V[i])
  99. tmp = V[i]
  100. V[i+1] = [A ^ tmp[0], B ^ tmp[1], C ^ tmp[2], D ^ tmp[3], E ^ tmp[4], F ^ tmp[5], G ^ tmp[6], H ^ tmp[7]]
  101. return V[loop_len]
  102. if __name__ == '__main__':
  103. get_class = SM3_PRE_PROCESS()
  104. # data = get_class.padding('abc', 0) # message is char
  105. # data = get_class.padding('abcd' * 16, 0) # message is char
  106. data = get_class.padding('61626364'*16, 1)
  107. cal_class = SM3_CALCU()
  108. data_hash = cal_class.loop_cal(data)
  109. for i in range(len(data_hash)):
  110. print(hex(data_hash[i]))

官网文档里面,给出了迭代过程的中间数据,其中有个错误,截图如下:

四 Verilog硬件实现

《最近时间忙,后续稍后补充》

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/139572?site
推荐阅读
相关标签
  

闽ICP备14008679号