25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 
 
 

253 satır
7.0 KiB

  1. """Implementation of Edwards Digital Signature Algorithm."""
  2. import hashlib
  3. from ._sha3 import shake_256
  4. from . import ellipticcurve
  5. from ._compat import (
  6. remove_whitespace,
  7. bit_length,
  8. bytes_to_int,
  9. int_to_bytes,
  10. compat26_str,
  11. )
  12. # edwards25519, defined in RFC7748
  13. _p = 2**255 - 19
  14. _a = -1
  15. _d = int(
  16. remove_whitespace(
  17. "370957059346694393431380835087545651895421138798432190163887855330"
  18. "85940283555"
  19. )
  20. )
  21. _h = 8
  22. _Gx = int(
  23. remove_whitespace(
  24. "151122213495354007725011514095885315114540126930418572060461132"
  25. "83949847762202"
  26. )
  27. )
  28. _Gy = int(
  29. remove_whitespace(
  30. "463168356949264781694283940034751631413079938662562256157830336"
  31. "03165251855960"
  32. )
  33. )
  34. _r = 2**252 + 0x14DEF9DEA2F79CD65812631A5CF5D3ED
  35. def _sha512(data):
  36. return hashlib.new("sha512", compat26_str(data)).digest()
  37. curve_ed25519 = ellipticcurve.CurveEdTw(_p, _a, _d, _h, _sha512)
  38. generator_ed25519 = ellipticcurve.PointEdwards(
  39. curve_ed25519, _Gx, _Gy, 1, _Gx * _Gy % _p, _r, generator=True
  40. )
  41. # edwards448, defined in RFC7748
  42. _p = 2**448 - 2**224 - 1
  43. _a = 1
  44. _d = -39081 % _p
  45. _h = 4
  46. _Gx = int(
  47. remove_whitespace(
  48. "224580040295924300187604334099896036246789641632564134246125461"
  49. "686950415467406032909029192869357953282578032075146446173674602635"
  50. "247710"
  51. )
  52. )
  53. _Gy = int(
  54. remove_whitespace(
  55. "298819210078481492676017930443930673437544040154080242095928241"
  56. "372331506189835876003536878655418784733982303233503462500531545062"
  57. "832660"
  58. )
  59. )
  60. _r = 2**446 - 0x8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D
  61. def _shake256(data):
  62. return shake_256(data, 114)
  63. curve_ed448 = ellipticcurve.CurveEdTw(_p, _a, _d, _h, _shake256)
  64. generator_ed448 = ellipticcurve.PointEdwards(
  65. curve_ed448, _Gx, _Gy, 1, _Gx * _Gy % _p, _r, generator=True
  66. )
  67. class PublicKey(object):
  68. """Public key for the Edwards Digital Signature Algorithm."""
  69. def __init__(self, generator, public_key, public_point=None):
  70. self.generator = generator
  71. self.curve = generator.curve()
  72. self.__encoded = public_key
  73. # plus one for the sign bit and round up
  74. self.baselen = (bit_length(self.curve.p()) + 1 + 7) // 8
  75. if len(public_key) != self.baselen:
  76. raise ValueError(
  77. "Incorrect size of the public key, expected: {0} bytes".format(
  78. self.baselen
  79. )
  80. )
  81. if public_point:
  82. self.__point = public_point
  83. else:
  84. self.__point = ellipticcurve.PointEdwards.from_bytes(
  85. self.curve, public_key
  86. )
  87. def __eq__(self, other):
  88. if isinstance(other, PublicKey):
  89. return (
  90. self.curve == other.curve and self.__encoded == other.__encoded
  91. )
  92. return NotImplemented
  93. def __ne__(self, other):
  94. return not self == other
  95. @property
  96. def point(self):
  97. return self.__point
  98. @point.setter
  99. def point(self, other):
  100. if self.__point != other:
  101. raise ValueError("Can't change the coordinates of the point")
  102. self.__point = other
  103. def public_point(self):
  104. return self.__point
  105. def public_key(self):
  106. return self.__encoded
  107. def verify(self, data, signature):
  108. """Verify a Pure EdDSA signature over data."""
  109. data = compat26_str(data)
  110. if len(signature) != 2 * self.baselen:
  111. raise ValueError(
  112. "Invalid signature length, expected: {0} bytes".format(
  113. 2 * self.baselen
  114. )
  115. )
  116. R = ellipticcurve.PointEdwards.from_bytes(
  117. self.curve, signature[: self.baselen]
  118. )
  119. S = bytes_to_int(signature[self.baselen :], "little")
  120. if S >= self.generator.order():
  121. raise ValueError("Invalid signature")
  122. dom = bytearray()
  123. if self.curve == curve_ed448:
  124. dom = bytearray(b"SigEd448" + b"\x00\x00")
  125. k = bytes_to_int(
  126. self.curve.hash_func(dom + R.to_bytes() + self.__encoded + data),
  127. "little",
  128. )
  129. if self.generator * S != self.__point * k + R:
  130. raise ValueError("Invalid signature")
  131. return True
  132. class PrivateKey(object):
  133. """Private key for the Edwards Digital Signature Algorithm."""
  134. def __init__(self, generator, private_key):
  135. self.generator = generator
  136. self.curve = generator.curve()
  137. # plus one for the sign bit and round up
  138. self.baselen = (bit_length(self.curve.p()) + 1 + 7) // 8
  139. if len(private_key) != self.baselen:
  140. raise ValueError(
  141. "Incorrect size of private key, expected: {0} bytes".format(
  142. self.baselen
  143. )
  144. )
  145. self.__private_key = bytes(private_key)
  146. self.__h = bytearray(self.curve.hash_func(private_key))
  147. self.__public_key = None
  148. a = self.__h[: self.baselen]
  149. a = self._key_prune(a)
  150. scalar = bytes_to_int(a, "little")
  151. self.__s = scalar
  152. @property
  153. def private_key(self):
  154. return self.__private_key
  155. def __eq__(self, other):
  156. if isinstance(other, PrivateKey):
  157. return (
  158. self.curve == other.curve
  159. and self.__private_key == other.__private_key
  160. )
  161. return NotImplemented
  162. def __ne__(self, other):
  163. return not self == other
  164. def _key_prune(self, key):
  165. # make sure the key is not in a small subgroup
  166. h = self.curve.cofactor()
  167. if h == 4:
  168. h_log = 2
  169. elif h == 8:
  170. h_log = 3
  171. else:
  172. raise ValueError("Only cofactor 4 and 8 curves supported")
  173. key[0] &= ~((1 << h_log) - 1)
  174. # ensure the highest bit is set but no higher
  175. l = bit_length(self.curve.p())
  176. if l % 8 == 0:
  177. key[-1] = 0
  178. key[-2] |= 0x80
  179. else:
  180. key[-1] = key[-1] & (1 << (l % 8)) - 1 | 1 << (l % 8) - 1
  181. return key
  182. def public_key(self):
  183. """Generate the public key based on the included private key"""
  184. if self.__public_key:
  185. return self.__public_key
  186. public_point = self.generator * self.__s
  187. self.__public_key = PublicKey(
  188. self.generator, public_point.to_bytes(), public_point
  189. )
  190. return self.__public_key
  191. def sign(self, data):
  192. """Perform a Pure EdDSA signature over data."""
  193. data = compat26_str(data)
  194. A = self.public_key().public_key()
  195. prefix = self.__h[self.baselen :]
  196. dom = bytearray()
  197. if self.curve == curve_ed448:
  198. dom = bytearray(b"SigEd448" + b"\x00\x00")
  199. r = bytes_to_int(self.curve.hash_func(dom + prefix + data), "little")
  200. R = (self.generator * r).to_bytes()
  201. k = bytes_to_int(self.curve.hash_func(dom + R + A + data), "little")
  202. k %= self.generator.order()
  203. S = (r + k * self.__s) % self.generator.order()
  204. return R + int_to_bytes(S, self.baselen, "little")