当前位置:   article > 正文

密码学的简单实现:求椭圆曲线上的点 | 平方剩余的点 | ECC加密解密 的python实现_椭圆曲线平方剩余

椭圆曲线平方剩余

有代码注释以及运行时的过程注释,有助于理解,可自行删除

代码如下

  1. from fractions import Fraction
  2. # 求x模y, 防止负数
  3. def QiuMo(x, y):
  4. while x < 0:
  5. x += y
  6. return x % y
  7. # 欧几里得算法
  8. def Exgcd(a, b):
  9. if b == 0:
  10. return 1, 0, a
  11. else:
  12. x, y, q = Exgcd(b, a % b)
  13. x, y = y, (x - (a // b) * y)
  14. return x, y, q
  15. # 求逆元,防止负数
  16. def Inf(a, p):
  17. x, y, q = Exgcd(a, p)
  18. if q != 1:
  19. raise Exception("No solution.")
  20. else:
  21. return (x + p) % p # 防止负数
  22. # 椭圆方程,需要初始化参数a,b,p
  23. class Equation:
  24. def __init__(self, a, b, p):
  25. self.a = a
  26. self.b = b
  27. self.p = p
  28. self.pfx = int((p - 1) / 2)
  29. self.pfy = int((p + 1) / 4)
  30. print(f"z=x^3+{a}x+{b}, p={p}, (p-1)/2={self.pfx}, (p+1)/2={self.pfy}")
  31. # 求在椭圆上的平方剩余的点
  32. def EquationResult(self, x):
  33. z = int(pow(x, 3) + self.a * x + self.b)
  34. z2 = z % self.p
  35. result = 1
  36. for i in range(self.pfx):
  37. result *= QiuMo(z2, self.p)
  38. result = QiuMo(result, self.p)
  39. result = int(QiuMo(result, self.p))
  40. r_string = f"x={x}时, z = {z}, z^(p-1)/2 mod p = {result}"
  41. if result == 1:
  42. y1 = int(QiuMo(pow(z, self.pfy), self.p))
  43. y2 = self.p - y1
  44. r_string += f" 是平方剩余, 点为({x},{y1})和({x},{y2})"
  45. else:
  46. r_string += " 不是平方剩余"
  47. return r_string
  48. # 计算椭圆曲线上的P + Q, 可传入提示信息
  49. def GetR_FromPQ(self, P, Q, string):
  50. print(f"{string}:\tP={P}, Q={Q}")
  51. s = "过程:"
  52. x1, y1 = P
  53. x2, y2 = Q
  54. if P == Q:
  55. l = Fraction(3 * x1 * x1 + self.a, 2 * y1)
  56. s += f"l={l}"
  57. else:
  58. assert x1 != x2, f"输入出错,过程出错:string={string},P={P},Q={Q},x1==x2,除数为零!"
  59. l = Fraction(y2 - y1, x2 - x1)
  60. s += f"l={l}"
  61. l_final = QiuMo(l.numerator * Inf(l.denominator, self.p), self.p)
  62. s += f"\tl_final={l_final}"
  63. x3 = QiuMo(int(-x1 - x2 + l_final * l_final), self.p)
  64. y3 = QiuMo(int(-y1 + l_final * (x1 - x3)), self.p)
  65. s += f"\tGF:{(x3, y3)}"
  66. print(s)
  67. return x3, y3
  68. # 计算椭圆曲线上的nG, 可传入提示信息
  69. def GetNG(self, n, G, string):
  70. nG = G
  71. for i in range(n - 1):
  72. nG = self.GetR_FromPQ(nG, G, string)
  73. return nG
  74. # 求逆元-G
  75. def getNi(self, G):
  76. x, y = G
  77. return x, -y
  78. # ECC加密,传入生成元G、私钥d,k,以及明文M,打印过程
  79. def ECCEncode(self, G, d, k, M):
  80. Y = self.GetNG(d, G, "正在计算Y=(d或x)G")
  81. c1 = self.GetNG(k, G, "正在计算c1=kG")
  82. kY = self.GetNG(k, Y, "正在计算kY")
  83. c2 = self.GetR_FromPQ(M, kY, "正在计算c2=M+kY")
  84. c = (c1, c2)
  85. return c
  86. # ECC解密,传入c2,c1,x,返回明文M
  87. def ECCDecode(self, c1, c2, x):
  88. return self.GetR_FromPQ(c2, self.getNi(self.GetNG(x, c1, f'求xc1:x={x},c1={c1}')), "ECC解密")
  89. if __name__ == '__main__':
  90. a, b, p = 1, 6, 11
  91. equation = Equation(a, b, p)
  92. print("正在进行求平方剩余的点")
  93. # 举例求平方剩余的点
  94. for i in range(p):
  95. print(equation.EquationResult(i))
  96. # 举例ECC加密
  97. print("正在进行ECC加密")
  98. G = (2, 7)
  99. d = 7
  100. k = 6
  101. M = (9, 1)
  102. # 加密
  103. C = equation.ECCEncode(G, d, k, M)
  104. c1, c2 = C
  105. # 解密
  106. M2 = equation.ECCDecode(c1, c2, d)
  107. print(f'\n对于G={G},d={d},k={k},M={M}')
  108. print(f"ECC加密结果:{C}")
  109. print(f"ECC解密结果:{M2}")

运行结果如图:

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

闽ICP备14008679号