ec.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. from __future__ import absolute_import, division, print_function
  5. import abc
  6. import warnings
  7. import six
  8. from cryptography import utils
  9. from cryptography.hazmat._oid import ObjectIdentifier
  10. from cryptography.hazmat.backends import _get_backend
  11. class EllipticCurveOID(object):
  12. SECP192R1 = ObjectIdentifier("1.2.840.10045.3.1.1")
  13. SECP224R1 = ObjectIdentifier("1.3.132.0.33")
  14. SECP256K1 = ObjectIdentifier("1.3.132.0.10")
  15. SECP256R1 = ObjectIdentifier("1.2.840.10045.3.1.7")
  16. SECP384R1 = ObjectIdentifier("1.3.132.0.34")
  17. SECP521R1 = ObjectIdentifier("1.3.132.0.35")
  18. BRAINPOOLP256R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.7")
  19. BRAINPOOLP384R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.11")
  20. BRAINPOOLP512R1 = ObjectIdentifier("1.3.36.3.3.2.8.1.1.13")
  21. SECT163K1 = ObjectIdentifier("1.3.132.0.1")
  22. SECT163R2 = ObjectIdentifier("1.3.132.0.15")
  23. SECT233K1 = ObjectIdentifier("1.3.132.0.26")
  24. SECT233R1 = ObjectIdentifier("1.3.132.0.27")
  25. SECT283K1 = ObjectIdentifier("1.3.132.0.16")
  26. SECT283R1 = ObjectIdentifier("1.3.132.0.17")
  27. SECT409K1 = ObjectIdentifier("1.3.132.0.36")
  28. SECT409R1 = ObjectIdentifier("1.3.132.0.37")
  29. SECT571K1 = ObjectIdentifier("1.3.132.0.38")
  30. SECT571R1 = ObjectIdentifier("1.3.132.0.39")
  31. @six.add_metaclass(abc.ABCMeta)
  32. class EllipticCurve(object):
  33. @abc.abstractproperty
  34. def name(self):
  35. """
  36. The name of the curve. e.g. secp256r1.
  37. """
  38. @abc.abstractproperty
  39. def key_size(self):
  40. """
  41. Bit size of a secret scalar for the curve.
  42. """
  43. @six.add_metaclass(abc.ABCMeta)
  44. class EllipticCurveSignatureAlgorithm(object):
  45. @abc.abstractproperty
  46. def algorithm(self):
  47. """
  48. The digest algorithm used with this signature.
  49. """
  50. @six.add_metaclass(abc.ABCMeta)
  51. class EllipticCurvePrivateKey(object):
  52. @abc.abstractmethod
  53. def signer(self, signature_algorithm):
  54. """
  55. Returns an AsymmetricSignatureContext used for signing data.
  56. """
  57. @abc.abstractmethod
  58. def exchange(self, algorithm, peer_public_key):
  59. """
  60. Performs a key exchange operation using the provided algorithm with the
  61. provided peer's public key.
  62. """
  63. @abc.abstractmethod
  64. def public_key(self):
  65. """
  66. The EllipticCurvePublicKey for this private key.
  67. """
  68. @abc.abstractproperty
  69. def curve(self):
  70. """
  71. The EllipticCurve that this key is on.
  72. """
  73. @abc.abstractproperty
  74. def key_size(self):
  75. """
  76. Bit size of a secret scalar for the curve.
  77. """
  78. @abc.abstractmethod
  79. def sign(self, data, signature_algorithm):
  80. """
  81. Signs the data
  82. """
  83. @six.add_metaclass(abc.ABCMeta)
  84. class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey):
  85. @abc.abstractmethod
  86. def private_numbers(self):
  87. """
  88. Returns an EllipticCurvePrivateNumbers.
  89. """
  90. @abc.abstractmethod
  91. def private_bytes(self, encoding, format, encryption_algorithm):
  92. """
  93. Returns the key serialized as bytes.
  94. """
  95. @six.add_metaclass(abc.ABCMeta)
  96. class EllipticCurvePublicKey(object):
  97. @abc.abstractmethod
  98. def verifier(self, signature, signature_algorithm):
  99. """
  100. Returns an AsymmetricVerificationContext used for signing data.
  101. """
  102. @abc.abstractproperty
  103. def curve(self):
  104. """
  105. The EllipticCurve that this key is on.
  106. """
  107. @abc.abstractproperty
  108. def key_size(self):
  109. """
  110. Bit size of a secret scalar for the curve.
  111. """
  112. @abc.abstractmethod
  113. def public_numbers(self):
  114. """
  115. Returns an EllipticCurvePublicNumbers.
  116. """
  117. @abc.abstractmethod
  118. def public_bytes(self, encoding, format):
  119. """
  120. Returns the key serialized as bytes.
  121. """
  122. @abc.abstractmethod
  123. def verify(self, signature, data, signature_algorithm):
  124. """
  125. Verifies the signature of the data.
  126. """
  127. @classmethod
  128. def from_encoded_point(cls, curve, data):
  129. utils._check_bytes("data", data)
  130. if not isinstance(curve, EllipticCurve):
  131. raise TypeError("curve must be an EllipticCurve instance")
  132. if len(data) == 0:
  133. raise ValueError("data must not be an empty byte string")
  134. if six.indexbytes(data, 0) not in [0x02, 0x03, 0x04]:
  135. raise ValueError("Unsupported elliptic curve point type")
  136. from cryptography.hazmat.backends.openssl.backend import backend
  137. return backend.load_elliptic_curve_public_bytes(curve, data)
  138. EllipticCurvePublicKeyWithSerialization = EllipticCurvePublicKey
  139. @utils.register_interface(EllipticCurve)
  140. class SECT571R1(object):
  141. name = "sect571r1"
  142. key_size = 570
  143. @utils.register_interface(EllipticCurve)
  144. class SECT409R1(object):
  145. name = "sect409r1"
  146. key_size = 409
  147. @utils.register_interface(EllipticCurve)
  148. class SECT283R1(object):
  149. name = "sect283r1"
  150. key_size = 283
  151. @utils.register_interface(EllipticCurve)
  152. class SECT233R1(object):
  153. name = "sect233r1"
  154. key_size = 233
  155. @utils.register_interface(EllipticCurve)
  156. class SECT163R2(object):
  157. name = "sect163r2"
  158. key_size = 163
  159. @utils.register_interface(EllipticCurve)
  160. class SECT571K1(object):
  161. name = "sect571k1"
  162. key_size = 571
  163. @utils.register_interface(EllipticCurve)
  164. class SECT409K1(object):
  165. name = "sect409k1"
  166. key_size = 409
  167. @utils.register_interface(EllipticCurve)
  168. class SECT283K1(object):
  169. name = "sect283k1"
  170. key_size = 283
  171. @utils.register_interface(EllipticCurve)
  172. class SECT233K1(object):
  173. name = "sect233k1"
  174. key_size = 233
  175. @utils.register_interface(EllipticCurve)
  176. class SECT163K1(object):
  177. name = "sect163k1"
  178. key_size = 163
  179. @utils.register_interface(EllipticCurve)
  180. class SECP521R1(object):
  181. name = "secp521r1"
  182. key_size = 521
  183. @utils.register_interface(EllipticCurve)
  184. class SECP384R1(object):
  185. name = "secp384r1"
  186. key_size = 384
  187. @utils.register_interface(EllipticCurve)
  188. class SECP256R1(object):
  189. name = "secp256r1"
  190. key_size = 256
  191. @utils.register_interface(EllipticCurve)
  192. class SECP256K1(object):
  193. name = "secp256k1"
  194. key_size = 256
  195. @utils.register_interface(EllipticCurve)
  196. class SECP224R1(object):
  197. name = "secp224r1"
  198. key_size = 224
  199. @utils.register_interface(EllipticCurve)
  200. class SECP192R1(object):
  201. name = "secp192r1"
  202. key_size = 192
  203. @utils.register_interface(EllipticCurve)
  204. class BrainpoolP256R1(object):
  205. name = "brainpoolP256r1"
  206. key_size = 256
  207. @utils.register_interface(EllipticCurve)
  208. class BrainpoolP384R1(object):
  209. name = "brainpoolP384r1"
  210. key_size = 384
  211. @utils.register_interface(EllipticCurve)
  212. class BrainpoolP512R1(object):
  213. name = "brainpoolP512r1"
  214. key_size = 512
  215. _CURVE_TYPES = {
  216. "prime192v1": SECP192R1,
  217. "prime256v1": SECP256R1,
  218. "secp192r1": SECP192R1,
  219. "secp224r1": SECP224R1,
  220. "secp256r1": SECP256R1,
  221. "secp384r1": SECP384R1,
  222. "secp521r1": SECP521R1,
  223. "secp256k1": SECP256K1,
  224. "sect163k1": SECT163K1,
  225. "sect233k1": SECT233K1,
  226. "sect283k1": SECT283K1,
  227. "sect409k1": SECT409K1,
  228. "sect571k1": SECT571K1,
  229. "sect163r2": SECT163R2,
  230. "sect233r1": SECT233R1,
  231. "sect283r1": SECT283R1,
  232. "sect409r1": SECT409R1,
  233. "sect571r1": SECT571R1,
  234. "brainpoolP256r1": BrainpoolP256R1,
  235. "brainpoolP384r1": BrainpoolP384R1,
  236. "brainpoolP512r1": BrainpoolP512R1,
  237. }
  238. @utils.register_interface(EllipticCurveSignatureAlgorithm)
  239. class ECDSA(object):
  240. def __init__(self, algorithm):
  241. self._algorithm = algorithm
  242. algorithm = utils.read_only_property("_algorithm")
  243. def generate_private_key(curve, backend=None):
  244. backend = _get_backend(backend)
  245. return backend.generate_elliptic_curve_private_key(curve)
  246. def derive_private_key(private_value, curve, backend=None):
  247. backend = _get_backend(backend)
  248. if not isinstance(private_value, six.integer_types):
  249. raise TypeError("private_value must be an integer type.")
  250. if private_value <= 0:
  251. raise ValueError("private_value must be a positive integer.")
  252. if not isinstance(curve, EllipticCurve):
  253. raise TypeError("curve must provide the EllipticCurve interface.")
  254. return backend.derive_elliptic_curve_private_key(private_value, curve)
  255. class EllipticCurvePublicNumbers(object):
  256. def __init__(self, x, y, curve):
  257. if not isinstance(x, six.integer_types) or not isinstance(
  258. y, six.integer_types
  259. ):
  260. raise TypeError("x and y must be integers.")
  261. if not isinstance(curve, EllipticCurve):
  262. raise TypeError("curve must provide the EllipticCurve interface.")
  263. self._y = y
  264. self._x = x
  265. self._curve = curve
  266. def public_key(self, backend=None):
  267. backend = _get_backend(backend)
  268. return backend.load_elliptic_curve_public_numbers(self)
  269. def encode_point(self):
  270. warnings.warn(
  271. "encode_point has been deprecated on EllipticCurvePublicNumbers"
  272. " and will be removed in a future version. Please use "
  273. "EllipticCurvePublicKey.public_bytes to obtain both "
  274. "compressed and uncompressed point encoding.",
  275. utils.PersistentlyDeprecated2019,
  276. stacklevel=2,
  277. )
  278. # key_size is in bits. Convert to bytes and round up
  279. byte_length = (self.curve.key_size + 7) // 8
  280. return (
  281. b"\x04"
  282. + utils.int_to_bytes(self.x, byte_length)
  283. + utils.int_to_bytes(self.y, byte_length)
  284. )
  285. @classmethod
  286. def from_encoded_point(cls, curve, data):
  287. if not isinstance(curve, EllipticCurve):
  288. raise TypeError("curve must be an EllipticCurve instance")
  289. warnings.warn(
  290. "Support for unsafe construction of public numbers from "
  291. "encoded data will be removed in a future version. "
  292. "Please use EllipticCurvePublicKey.from_encoded_point",
  293. utils.PersistentlyDeprecated2019,
  294. stacklevel=2,
  295. )
  296. if data.startswith(b"\x04"):
  297. # key_size is in bits. Convert to bytes and round up
  298. byte_length = (curve.key_size + 7) // 8
  299. if len(data) == 2 * byte_length + 1:
  300. x = utils.int_from_bytes(data[1 : byte_length + 1], "big")
  301. y = utils.int_from_bytes(data[byte_length + 1 :], "big")
  302. return cls(x, y, curve)
  303. else:
  304. raise ValueError("Invalid elliptic curve point data length")
  305. else:
  306. raise ValueError("Unsupported elliptic curve point type")
  307. curve = utils.read_only_property("_curve")
  308. x = utils.read_only_property("_x")
  309. y = utils.read_only_property("_y")
  310. def __eq__(self, other):
  311. if not isinstance(other, EllipticCurvePublicNumbers):
  312. return NotImplemented
  313. return (
  314. self.x == other.x
  315. and self.y == other.y
  316. and self.curve.name == other.curve.name
  317. and self.curve.key_size == other.curve.key_size
  318. )
  319. def __ne__(self, other):
  320. return not self == other
  321. def __hash__(self):
  322. return hash((self.x, self.y, self.curve.name, self.curve.key_size))
  323. def __repr__(self):
  324. return (
  325. "<EllipticCurvePublicNumbers(curve={0.curve.name}, x={0.x}, "
  326. "y={0.y}>".format(self)
  327. )
  328. class EllipticCurvePrivateNumbers(object):
  329. def __init__(self, private_value, public_numbers):
  330. if not isinstance(private_value, six.integer_types):
  331. raise TypeError("private_value must be an integer.")
  332. if not isinstance(public_numbers, EllipticCurvePublicNumbers):
  333. raise TypeError(
  334. "public_numbers must be an EllipticCurvePublicNumbers "
  335. "instance."
  336. )
  337. self._private_value = private_value
  338. self._public_numbers = public_numbers
  339. def private_key(self, backend=None):
  340. backend = _get_backend(backend)
  341. return backend.load_elliptic_curve_private_numbers(self)
  342. private_value = utils.read_only_property("_private_value")
  343. public_numbers = utils.read_only_property("_public_numbers")
  344. def __eq__(self, other):
  345. if not isinstance(other, EllipticCurvePrivateNumbers):
  346. return NotImplemented
  347. return (
  348. self.private_value == other.private_value
  349. and self.public_numbers == other.public_numbers
  350. )
  351. def __ne__(self, other):
  352. return not self == other
  353. def __hash__(self):
  354. return hash((self.private_value, self.public_numbers))
  355. class ECDH(object):
  356. pass
  357. _OID_TO_CURVE = {
  358. EllipticCurveOID.SECP192R1: SECP192R1,
  359. EllipticCurveOID.SECP224R1: SECP224R1,
  360. EllipticCurveOID.SECP256K1: SECP256K1,
  361. EllipticCurveOID.SECP256R1: SECP256R1,
  362. EllipticCurveOID.SECP384R1: SECP384R1,
  363. EllipticCurveOID.SECP521R1: SECP521R1,
  364. EllipticCurveOID.BRAINPOOLP256R1: BrainpoolP256R1,
  365. EllipticCurveOID.BRAINPOOLP384R1: BrainpoolP384R1,
  366. EllipticCurveOID.BRAINPOOLP512R1: BrainpoolP512R1,
  367. EllipticCurveOID.SECT163K1: SECT163K1,
  368. EllipticCurveOID.SECT163R2: SECT163R2,
  369. EllipticCurveOID.SECT233K1: SECT233K1,
  370. EllipticCurveOID.SECT233R1: SECT233R1,
  371. EllipticCurveOID.SECT283K1: SECT283K1,
  372. EllipticCurveOID.SECT283R1: SECT283R1,
  373. EllipticCurveOID.SECT409K1: SECT409K1,
  374. EllipticCurveOID.SECT409R1: SECT409R1,
  375. EllipticCurveOID.SECT571K1: SECT571K1,
  376. EllipticCurveOID.SECT571R1: SECT571R1,
  377. }
  378. def get_curve_for_oid(oid):
  379. try:
  380. return _OID_TO_CURVE[oid]
  381. except KeyError:
  382. raise LookupError(
  383. "The provided object identifier has no matching elliptic "
  384. "curve class"
  385. )