当前位置:   article > 正文

二元扩域sm2签名与验签算法python实现(已封装,可直接使用)_python sm2

python sm2

   文件1——sm3.py:

  1. class SM3:
  2. def __init__(self, encoding='ascii'): # encodine:ascii/utf-8/gbk
  3. self.IV = [0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e]
  4. self.encoding = encoding
  5. def cshift_left(self, x, l):
  6. while l >= 32:
  7. l -= 32
  8. x = x & 0xffffffff
  9. bin_x = '{:032b}'.format(x)
  10. bin_x = bin_x[l:] + bin_x[:l]
  11. return int(bin_x, 2)
  12. def Tj(self, j):
  13. if (j < 16):
  14. return 0x79cc4519
  15. else:
  16. return 0x7a879d8a
  17. def FFj(self, x, y, z, j):
  18. if j < 16:
  19. return x ^ y ^ z
  20. else:
  21. return (x & y) | (x & z) | (y & z)
  22. def GGj(self, x, y, z, j):
  23. if j < 16:
  24. return x ^ y ^ z
  25. else:
  26. return (x & y) | (~x & z)
  27. def P0(self, x):
  28. return x ^ self.cshift_left(x, 9) ^ self.cshift_left(x, 17)
  29. def P1(self, x):
  30. return x ^ self.cshift_left(x, 15) ^ self.cshift_left(x, 23)
  31. def padding(self, msg):
  32. msg_len = len(msg)
  33. msg_blen = msg_len << 3
  34. m, n = msg_len >> 2, msg_len & 3
  35. block = []
  36. one_block = []
  37. if type(msg) == type(''):
  38. bt_msg = msg.encode(encoding=self.encoding, errors='strict')
  39. elif type(msg) == type(0):
  40. bt_msg = msg.to_bytes((msg.bit_length() + 7) // 8, "big")
  41. else:
  42. bt_msg = msg
  43. for i in range(m):
  44. wd = bt_msg[0] << 24 | bt_msg[1] << 16 | bt_msg[2] << 8 | bt_msg[3]
  45. one_block.append(wd)
  46. bt_msg = bt_msg[4:]
  47. if i & 15 == 15:
  48. block.append(one_block.copy())
  49. one_block.clear()
  50. if n == 0:
  51. new_wd = 0x80 << 24
  52. elif n == 1:
  53. new_wd = bt_msg[0] << 24 | 0x80 << 16
  54. elif n == 2:
  55. new_wd = bt_msg[0] << 24 | bt_msg[1] << 16 | 0x80 << 8
  56. else:
  57. new_wd = bt_msg[0] << 24 | bt_msg[1] << 16 | bt_msg[2] << 8 | 0x80
  58. one_block.append(new_wd)
  59. ob_len = len(one_block)
  60. if ob_len <= 14:
  61. for i in range(14 - ob_len):
  62. one_block.append(0)
  63. one_block.append(msg_blen >> 32)
  64. one_block.append(msg_blen & 0xffffffff)
  65. block.append(one_block.copy())
  66. else:
  67. for i in range(16 - ob_len):
  68. one_block.append(0)
  69. block.append(one_block.copy())
  70. one_block = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, msg_blen >> 32, msg_blen & 0xffffffff]
  71. block.append(one_block.copy())
  72. return block
  73. def CF(self, V, B):
  74. W0, W1 = B.copy(), []
  75. for i in range(16, 68):
  76. wd = self.P1(W0[i - 16] ^ W0[i - 9] ^ self.cshift_left(W0[i - 3], 15)) ^ self.cshift_left(W0[i - 13], 7) ^ \
  77. W0[i - 6]
  78. W0.append(wd)
  79. for i in range(64):
  80. W1.append(W0[i] ^ W0[i + 4])
  81. A, B, C, D, E, F, G, H = V
  82. for i in range(64):
  83. SS1 = (self.cshift_left(self.cshift_left(A, 12) + E + self.cshift_left(self.Tj(i), i), 7)) & 0xffffffff
  84. SS2 = SS1 ^ self.cshift_left(A, 12)
  85. TT1 = (self.FFj(A, B, C, i) + D + SS2 + W1[i]) & 0xffffffff
  86. TT2 = (self.GGj(E, F, G, i) + H + SS1 + W0[i]) & 0xffffffff
  87. D = C
  88. C = self.cshift_left(B, 9)
  89. B = A
  90. A = TT1
  91. H = G
  92. G = self.cshift_left(F, 19)
  93. F = E
  94. E = self.P0(TT2)
  95. return A, B, C, D, E, F, G, H
  96. def compression(self, msg):
  97. block = self.padding(msg)
  98. V = self.IV
  99. for bi in block:
  100. res = self.CF(V, bi)
  101. for i in range(8):
  102. V[i] = V[i] ^ res[i]
  103. res = b''
  104. for v in V:
  105. res = res + v.to_bytes(4, "big")
  106. return res
  107. if __name__ == '__main__':
  108. msg = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"
  109. sm3 = SM3()
  110. res = sm3.compression(msg)
  111. i = 0
  112. for b in res:
  113. print("%02x" % b, end="")
  114. if i & 3 == 3: print("", end=" ")
  115. i = i + 1

文件二——ecc_2m.py

  1. '''
  2. 二元扩域模运算和点运算工具类
  3. '''
  4. class ECC_2m:
  5. def __init__(self,poly,Gx,Gy,ecc_a=1,ecc_b=1):
  6. self.poly=poly
  7. self.ecc_a=ecc_a
  8. self.ecc_b=ecc_b
  9. self.Gx=Gx
  10. self.Gy=Gy
  11. def gf2_divmod(self,a, b):
  12. if b == 0:
  13. raise ZeroDivisionError
  14. ans = 0
  15. digit_a, digit_b = a.bit_length(), b.bit_length()
  16. while not a < b:
  17. rec = digit_a - digit_b
  18. a = a ^ (b << rec)
  19. ans = ans | (1 << rec)
  20. digit_a = a.bit_length()
  21. return ans, a
  22. def gf2_ex_gcd(self,a,b):
  23. x1, y1, x2, y2 = 1, 0, 0, 1
  24. while b:
  25. q, r = self.gf2_divmod(a, b)
  26. a, b = b, r
  27. x1, x2 = x2, x1 ^ self.gf2_mul(q, x2)
  28. y1, y2 = y2, y1 ^ self.gf2_mul(q, y2)
  29. return a, x1, y1
  30. '''res = a*b mod poly'''
  31. def gf2_mul(self,a,b):
  32. ans = 0
  33. digit_1 = self.poly.bit_length() - 1
  34. while b:
  35. if b & 1:
  36. ans = ans ^ a
  37. a, b = a << 1, b >> 1
  38. if a >> digit_1:
  39. a = a ^ self.poly
  40. return ans
  41. '''res = a^-1 mod poly'''
  42. def gf2_inverse(self,a):
  43. x1, x2 = 1, 0
  44. b = self.poly
  45. while b:
  46. q, r = self.gf2_divmod(a, b)
  47. a, b = b, r
  48. x1, x2 = x2, x1 ^ self.gf2_mul(q, x2)
  49. return x1
  50. '''res = a^k mod poly'''
  51. def gf2_quick_pow_mod(self,a,k):
  52. res = 1
  53. while k:
  54. if k & 1:
  55. res = self.gf2_mul(res, a)
  56. k = k // 2
  57. a = self.gf2_mul(a, a)
  58. return res
  59. '''仿射坐标点加运算'''
  60. def affine_pt_add(self,x1,y1,x2,y2):
  61. inv=self.gf2_inverse(x2^x1)
  62. nmd=self.gf2_mul(y2 ^ y1, inv)
  63. nmd2=self.gf2_mul(nmd, nmd)
  64. x3=nmd2^nmd^x1^x2^self.ecc_a
  65. t=self.gf2_mul(x1 ^ x3, nmd)
  66. y3=t^x3^y1
  67. return x3,y3
  68. '''仿射坐标倍点运算'''
  69. def affine_pt_double(self,x1,y1):
  70. inv=self.gf2_inverse(x1)
  71. nmd=x1^self.gf2_mul(y1, inv)
  72. nmd2=self.gf2_mul(nmd, nmd)
  73. x2=nmd2^nmd^self.ecc_a
  74. xx1=self.gf2_mul(x1, x1)
  75. t=self.gf2_mul(nmd ^ 1, x2)
  76. y2=xx1^t
  77. return x2,y2
  78. '''标准投影坐标点加运算'''
  79. def sproject_pt_add(self,x1,z1,x2,z2,Px):
  80. p=self.gf2_mul(x1, z2)
  81. q=self.gf2_mul(x2, z1)
  82. z3=self.gf2_mul(p ^ q, p ^ q)
  83. m=self.gf2_mul(p, q)
  84. n=self.gf2_mul(Px,z3)
  85. x3=m^n
  86. return x3,z3
  87. '''标准投影坐标倍点运算'''
  88. def sproject_pt_double(self, x1, z1):
  89. xx1=self.gf2_mul(x1, x1)
  90. zz1=self.gf2_mul(z1,z1)
  91. z2=self.gf2_mul(xx1,zz1)
  92. x14=self.gf2_mul(xx1,xx1)
  93. z14=self.gf2_mul(zz1,zz1)
  94. bz=self.gf2_mul(self.ecc_b,z14)
  95. x2=x14^bz
  96. return x2,z2
  97. '''仿射坐标下二进制展开法多倍点运算'''
  98. def affine_pt_mul(self,k,Px,Py):
  99. lbk=bin(k)[3:]
  100. Qx,Qy=Px,Py
  101. for i in lbk:
  102. Qx,Qy=self.affine_pt_double(Qx,Qy)
  103. if int(i):
  104. Qx, Qy=self.affine_pt_add(Qx,Qy,Px,Py)
  105. return Qx,Qy
  106. '''标准投影坐标下蒙格玛利多倍点运算'''
  107. def montgomery_pt_mul(self,k,Px,Py):
  108. lbk = bin(k)[3:]
  109. x1,z1=Px,1
  110. z2=self.gf2_mul(Px,Px)
  111. x2=self.gf2_mul(z2,z2)^self.ecc_b
  112. for i in lbk:
  113. if int(i):
  114. x1,z1=self.sproject_pt_add(x1,z1,x2,z2,Px)
  115. x2,z2=self.sproject_pt_double(x2,z2)
  116. else:
  117. x2,z2=self.sproject_pt_add(x2,z2,x1,z1,Px)
  118. x1,z1=self.sproject_pt_double(x1,z1)
  119. t0=self.gf2_mul(Px,z1)
  120. t1=self.gf2_mul(t0,z2)
  121. inv=self.gf2_inverse(t1)
  122. t2=self.gf2_mul(Px,z2)
  123. t3=self.gf2_mul(t2,x1)
  124. Qx=self.gf2_mul(t3,inv)
  125. t4=self.gf2_mul(t0,x2)
  126. m=self.gf2_mul(t4,inv)
  127. t5=self.gf2_mul(Qx^Px,m^Px)
  128. t6=self.gf2_mul(Px,Px)
  129. t7=t5^t6^Py
  130. t8=self.gf2_mul(t7,Qx^Px)
  131. t9=self.gf2_mul(z1,z2)
  132. t10=self.gf2_mul(t8,t9)
  133. Qy=self.gf2_mul(t10,inv)^Py
  134. return Qx,Qy
  135. if __name__ == '__main__':
  136. k = 0x36CD79FC8E24B7357A8A7B4A46D454C397703D6498158C605399B341ADA186D6
  137. Gx = 0x00CDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD
  138. Gy = 0x013DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E
  139. poly = 0x20000000000000000000000000000000000000000000000000000000000001001
  140. b = 0x00E78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B
  141. a = 0
  142. ECC = ECC_2m(poly, Gx, Gy, a, b)
  143. '''计算Q=[k]G'''
  144. # Qx,Qy=ECC.affine_pt_mul(k,Gx,Gy)
  145. Qx, Qy = ECC.montgomery_pt_mul(k, Gx, Gy)
  146. # 目标值:
  147. Qx_right = 0x03fd87d6947a15f9425b32edd39381adfd5e71cd4bb357e3c6a6e0397eea7cd66
  148. Qy_right = 0x0807711146d73951e9eb373a658214054b7b56d1d50b4cd6eb32ed387a65aa6a2
  149. if (Qx == Qx_right) & (Qy == Qy_right):
  150. print("#####计算正确#####")
  151. else:
  152. print("*****计算错误*****")

文件3——sm2_2m.py

  1. from sm3 import SM3
  2. from ecc_2m import ECC_2m
  3. class SM2_2m:
  4. def __init__(self, poly, Gx=0, Gy=0, n=0, ecc_a=1, ecc_b=1, dA=0, pA_x=0, pA_y=0, ID='', encoding='ascii'):
  5. self.poly = poly
  6. self.encoding = encoding
  7. self.set_ecc(Gx, Gy, n, ecc_a, ecc_b)
  8. self.set_key(dA, pA_x, pA_y)
  9. self.set_ID(ID)
  10. def set_ecc(self, Gx, Gy, n, ecc_a, ecc_b):
  11. self.Gx = Gx
  12. self.Gy = Gy
  13. self.n = n
  14. self.ecc_a = ecc_a
  15. self.ecc_b = ecc_b
  16. def set_key(self, dA, pA_x, pA_y):
  17. self.dA = dA
  18. self.pA_x = pA_x
  19. self.pA_y = pA_y
  20. def set_ID(self, ID):
  21. if type(ID) == type(''):
  22. self.ID = ID.encode(encoding=self.encoding, errors='strict')
  23. elif type(ID) == type(0):
  24. self.ID = ID.to_bytes((ID.bit_length() + 7) // 8, "big")
  25. else:
  26. self.ID = ID
  27. blen_ID = (len(self.ID) << 3) & 0xffff
  28. h = (blen_ID >> 8).to_bytes(1, "big")
  29. l = (blen_ID & 0xff).to_bytes(1, "big")
  30. self.ENTLA = h + l
  31. def pf_pow(self, a, k):
  32. e = k % (self.n - 1)
  33. if e == 0: return 1
  34. lbe = bin(e)[3:]
  35. x = a
  36. for i in lbe:
  37. x = x * x % self.n
  38. if int(i): x = a * x % self.n
  39. return x
  40. def pf_inverse(self, a):
  41. return self.pf_pow(a, self.n - 2)
  42. def get_ZA(self):
  43. msg = self.ENTLA + self.ID
  44. bytes_len = (self.poly.bit_length() + 6) // 8
  45. bytes_a = self.ecc_a.to_bytes(bytes_len, "big")
  46. bytes_b = self.ecc_b.to_bytes(bytes_len, "big")
  47. bytes_Gx = self.Gx.to_bytes(bytes_len, "big")
  48. bytes_Gy = self.Gy.to_bytes(bytes_len, "big")
  49. bytes_Ax = self.pA_x.to_bytes(bytes_len, "big")
  50. bytes_Ay = self.pA_y.to_bytes(bytes_len, "big")
  51. msg = msg + bytes_a + bytes_b + bytes_Gx + bytes_Gy + bytes_Ax + bytes_Ay
  52. sm3 = SM3()
  53. ZA = sm3.compression(msg)
  54. return ZA
  55. def get_e(self, msg):
  56. if type(msg) == type(''):
  57. bt_msg = msg.encode(encoding=self.encoding, errors='strict')
  58. elif type(msg) == type(0):
  59. bt_msg = msg.to_bytes((msg.bit_length() + 7) // 8, "big")
  60. else:
  61. bt_msg = msg
  62. M = self.get_ZA() + bt_msg
  63. sm3 = SM3()
  64. bytes_e = sm3.compression(M)
  65. e = int.from_bytes(bytes_e, 'big')
  66. return e
  67. def signature(self, k, msg):
  68. e = self.get_e(msg)
  69. ECC = ECC_2m(self.poly, self.Gx, self.Gy, self.ecc_a, self.ecc_b)
  70. x1, y1 = ECC.montgomery_pt_mul(k, self.Gx, self.Gy)
  71. r = (e + x1) % self.n
  72. inv_dA = self.pf_inverse(1 + self.dA)
  73. rdA = (k - r * self.dA) % self.n
  74. s = inv_dA * rdA % n
  75. bytes_r = r.to_bytes(32, "big")
  76. bytes_s = s.to_bytes(32, "big")
  77. return bytes_r, bytes_s
  78. def verify(self, msg, r, s):
  79. e = self.get_e(msg)
  80. r = int.from_bytes(r, 'big')
  81. s = int.from_bytes(s, 'big')
  82. t = (r + s) % self.n
  83. ECC = ECC_2m(self.poly, self.Gx, self.Gy, self.ecc_a, self.ecc_b)
  84. xx1, yy1 = ECC.montgomery_pt_mul(s, self.Gx, self.Gy)
  85. xx2, yy2 = ECC.montgomery_pt_mul(t, self.pA_x, self.pA_y)
  86. x1, y1 = ECC.affine_pt_add(xx1, yy1, xx2, yy2)
  87. R = (e + x1) % self.n
  88. if R == r:
  89. print("****验证通过****")
  90. else:
  91. print("####验证失败####")
  92. if __name__ == '__main__':
  93. poly = 0x20000000000000000000000000000000000000000000000000000000000001001
  94. Gx = 0xCDB9CA7F1E6B0441F658343F4B10297C0EF9B6491082400A62E7A7485735FADD
  95. Gy = 0x13DE74DA65951C4D76DC89220D5F7777A611B1C38BAE260B175951DC8060C2B3E
  96. n = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC972CF7E6B6F900945B3C6A0CF6161D
  97. b = 0xE78BCD09746C202378A7E72B12BCE00266B9627ECB0B5A25367AD1AD4CC6242B
  98. a = 0x0
  99. dA = 0x771EF3DBFF5F1CDC32B9C572930476191998B2BF7CB981D7F5B39202645F0931
  100. pA_x = 0x165961645281A8626607B917F657D7E9382F1EA5CD931F40F6627F357542653B2
  101. pA_y = 0x1686522130D590FB8DE635D8FCA715CC6BF3D05BEF3F75DA5D543454448166612
  102. ID = 0x414C494345313233405941484F4F2E434F4D
  103. k = 0x36CD79FC8E24B7357A8A7B4A46D454C397703D6498158C605399B341ADA186D6
  104. msg = "message digest"
  105. sm2 = SM2_2m(poly, Gx, Gy, n, a, b, dA, pA_x, pA_y, ID)
  106. r, s = sm2.signature(k, msg)
  107. print("开始签名:\nr:", end="")
  108. i = 0
  109. for rr in r:
  110. print("%02x" % rr, end="")
  111. print("\ns:", end="")
  112. for ss in s:
  113. print("%02x" % ss, end="")
  114. print("\n开始验签:")
  115. sm2.verify(msg, r, s)

有问题欢迎评论和私信~~~~~~~

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

闽ICP备14008679号