当前位置:   article > 正文

SM2椭圆曲线公钥密码算法实现项目_sm2算法实现

sm2算法实现

 一、实验目的

Python 3.9 、PyCharm

二、方案设计

1.背景:

SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。

2.原理:

(1)有限域上的椭圆曲线上的点的加法

(2)dB*C1=dB*k*G=k*(dB*G)=k*PB,这样保证了密钥在加密过程和解密过程中是一致的。

(3)哈希函数输出杂凑值

(4)Hass定理

3.算法步骤:

加密过程:

    设需要发送的消息为比特串M ,klen为M的比特长度。

    为了对明文M进行加密,作为加密者的用户A应实现以下运算步骤:

    A1:用随机数发生器产生随机数k∈[1,n-1];

    A2:计算椭圆曲线点 C1=[k]G=(x1,y1),([k]G 表示 k*G )将C1的数据类型转换为比特串;

    A3:计算椭圆曲线点 S=[h]PB,若S是无穷远点,则报错并退出;

    A4:计算椭圆曲线点 [k]PB=(x2,y2),将坐标 x2、y2 的数据类型转换为比特串;

    A5:计算t=KDF(x2∥y2,klen),若 t 为全0比特串,则返回 A1;

    A6:计算C2 = M⊕t;

    A7:计算C3 = Hash(x2∥M∥y2);

    A8:输出密文C = C1∥C2∥C3。

解密过程:

    设klen为密文中C2的比特长度。

    为了对密文C=C1∥C2∥C3 进行解密,作为解密者的用户B应实现以下运算步骤:

    B1:从C中取出比特串C1,将C1的数据类型转换为椭圆曲线上的点,验证C1是否满足椭圆曲线方程,若不满足则报错并退出;

    B2:计算椭圆曲线点 S=[h]C1,若S是无穷远点,则报错并退出;

    B3:计算[dB]C1=(x2,y2),将坐标x2、y2的数据类型转换为比特串;

    B4:计算t=KDF(x2∥y2,klen),若t为全0比特串,则报错并退出;

    B5:从C中取出比特串C2,计算M′= C2⊕t;

    B6:计算u = Hash(x2∥M′∥y2),从C中取出比特串C3,若u != C3,则报错并退出;

    B7:输出明文M′。

三、方案实现

算法流程图:

 

四、实验源码 

1.主要函数

addPoint:点加运算

multiPoint:多倍点运算

KDF:产生长度为klen的密钥数据比特串

enCryto:加密函数

deCryto:解密函数

2.代码

  1. import hashlib
  2. import math
  3. import random
  4. import sys
  5. class SM2:
  6. def getInverse(self,a):
  7. return pow(a,self.p-2,self.p)
  8. def addPoint(self,pointA,pointB=None):
  9. if pointB==None:
  10. temp=(3*pow(pointA[0],2)+self.a)*self.getInverse((2*pointA[1]))
  11. x3=temp**2-2*pointA[0]
  12. x3%=self.p
  13. y3=temp*(pointA[0]-x3)-pointA[1]
  14. y3%=self.p
  15. elif pointA==[0,0] or pointB==[0,0]:
  16. x3=pointA[0]+pointB[0]
  17. y3=pointA[1]+pointB[1]
  18. else:
  19. temp=(pointA[1]-pointB[1])*self.getInverse(pointA[0]-pointB[0])
  20. x3=temp**2-pointA[0]-pointB[0]
  21. x3%=self.p
  22. y3=temp*(pointA[0]-x3)-pointA[1]
  23. y3%=self.p
  24. return x3,y3
  25. def multiPoint(self,point,k):
  26. multiPoint=[0,0]
  27. doublePoint=point
  28. while k>0:
  29. if k%2:
  30. multiPoint[0],multiPoint[1]=self.addPoint(multiPoint,doublePoint)
  31. k//=2
  32. doublePoint=self.addPoint(doublePoint)
  33. return multiPoint[0],multiPoint[1]
  34. def hex(self,num):
  35. num=hex(num).upper()[2:]
  36. return "0"*(64-len(num))+num
  37. def KDF(self,bitnum,klen):
  38. Ha=""
  39. hs=hashlib.sha256() #产生长度为64的十六进制字符串作为消息摘要
  40. if klen>(2**32-1)*64:
  41. print("too long to caculate")
  42. rct=math.ceil(klen/64)
  43. for i in range(rct):
  44. ct=hex(i+1).upper()[2:]
  45. ct="0"*(32-len(ct))+ct
  46. x2y2ct=bitnum+ct
  47. hs.update(x2y2ct.encode("ascii"))
  48. Ha+=hs.hexdigest() #返回摘要,作为十六进制数据字符串值
  49. return Ha[0:klen]
  50. def __init__(self):
  51. self.p=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
  52. self.a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
  53. self.b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93
  54. self.n=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123
  55. self.Gx=0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7
  56. self.Gy=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
  57. self.h=1 #Hass定理
  58. self.setSecretKey(True)
  59. self.PBx,self.PBy=self.multiPoint([self.Gx,self.Gy],self.d)
  60. print("公钥:({},{})".format(self.hex(self.PBx),self.hex(self.PBy)))
  61. if self.PBx+self.PBy==0:
  62. sys.exit(-1)
  63. hs=hashlib.sha256()
  64. def setSecretKey(self,show=False):
  65. self.d=random.randint(1,self.n)
  66. if show:
  67. print("私钥为:",self.hex(self.d))
  68. def enCryto(self,s:str):
  69. numt=0
  70. while numt==0:
  71. k=random.randint(1,self.n) #A1
  72. print("加密过程中生成随机数",self.hex(k))
  73. c1x,c1y=self.multiPoint([self.Gx,self.Gy],k) #A2
  74. print("C1点的坐标:({},{})".format(self.hex(c1x),self.hex(c1y)))
  75. C1=self.hex(c1x)+self.hex(c1y)
  76. print("C1为:",C1)
  77. x2,y2=self.multiPoint([self.PBx,self.PBy],k) #A4
  78. x2y2connet=hex(x2).upper()[2:]+hex(y2).upper()[2:]
  79. s=s.encode("ascii")
  80. s=s.hex()
  81. klen=len(s)
  82. t=self.KDF(x2y2connet,klen).upper() #A5
  83. print(t)
  84. numt=int(t,16)
  85. C2=hex(int(s,16)^int(t,16)).upper()[2:]
  86. print("C2为:",C2)
  87. print(x2,s,y2,"?")
  88. C3=self.hex(x2)+s+self.hex(y2)
  89. hs=hashlib.sha256()
  90. hs.update(C3.encode("ascii"))
  91. C3=hs.hexdigest().upper()
  92. print("C3为:",C3)
  93. return C1+C2+C3
  94. def deCryto(self,c1c2c3):
  95. clen=len(c1c2c3) #切片
  96. c1=c1c2c3[0:128]
  97. c2=c1c2c3[128:clen-64]
  98. c3=c1c2c3[-64:]
  99. x1=c1[0:64]
  100. y1=c1[64:128]
  101. x1=int(x1,16)
  102. y1=int(y1,16)
  103. left=pow(y1,2,self.p)
  104. right=pow(x1,3,self.p)+self.a*x1+self.b
  105. right%=self.p
  106. if left!=right: #C1和S验证
  107. sys.exit(-1)
  108. x2,y2=self.multiPoint([x1,y1],self.d)
  109. print("x2为:",x2)
  110. print("y2为:",y2)
  111. x2y2connet=hex(x2).upper()[2:]+hex(y2).upper()[2:]
  112. t=self.KDF(x2y2connet,len(c2))
  113. if int(t,16)==0:
  114. sys.exit(-1)
  115. Mm=hex(int(c2,16)^int(t,16)).upper()[2:]
  116. print("M`为:",Mm)
  117. u=self.hex(x2)+Mm+self.hex(y2)
  118. hs=hashlib.sha256()
  119. hs.update(u.encode("ascii"))
  120. print("x2||M||y2的哈希为:",hs.hexdigest().upper())
  121. if hs.hexdigest().upper()!=c3:
  122. sys.exit(-1)
  123. return bytes.fromhex(Mm)
  124. def main():
  125. plaintxt=input()
  126. sm2=SM2()
  127. secret=sm2.enCryto(plaintxt)
  128. print("密文为:",secret)
  129. msg=sm2.deCryto(secret)
  130. print("明文为:",msg.decode("ascii"))
  131. if __name__=="__main__":
  132. main()

五、数据分析

椭圆曲线参数:

 实验数据:

 结果分析:运行得到的明文与输入的明文一致。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/article/detail/50056
推荐阅读
相关标签
  

闽ICP备14008679号