選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

591 行
16 KiB

  1. from __future__ import division
  2. from six import PY2
  3. from . import der, ecdsa, ellipticcurve, eddsa
  4. from .util import orderlen, number_to_string, string_to_number
  5. from ._compat import normalise_bytes, bit_length
  6. # orderlen was defined in this module previously, so keep it in __all__,
  7. # will need to mark it as deprecated later
  8. __all__ = [
  9. "UnknownCurveError",
  10. "orderlen",
  11. "Curve",
  12. "SECP112r1",
  13. "SECP112r2",
  14. "SECP128r1",
  15. "SECP160r1",
  16. "NIST192p",
  17. "NIST224p",
  18. "NIST256p",
  19. "NIST384p",
  20. "NIST521p",
  21. "curves",
  22. "find_curve",
  23. "curve_by_name",
  24. "SECP256k1",
  25. "BRAINPOOLP160r1",
  26. "BRAINPOOLP160t1",
  27. "BRAINPOOLP192r1",
  28. "BRAINPOOLP192t1",
  29. "BRAINPOOLP224r1",
  30. "BRAINPOOLP224t1",
  31. "BRAINPOOLP256r1",
  32. "BRAINPOOLP256t1",
  33. "BRAINPOOLP320r1",
  34. "BRAINPOOLP320t1",
  35. "BRAINPOOLP384r1",
  36. "BRAINPOOLP384t1",
  37. "BRAINPOOLP512r1",
  38. "BRAINPOOLP512t1",
  39. "PRIME_FIELD_OID",
  40. "CHARACTERISTIC_TWO_FIELD_OID",
  41. "Ed25519",
  42. "Ed448",
  43. ]
  44. PRIME_FIELD_OID = (1, 2, 840, 10045, 1, 1)
  45. CHARACTERISTIC_TWO_FIELD_OID = (1, 2, 840, 10045, 1, 2)
  46. class UnknownCurveError(Exception):
  47. pass
  48. class Curve:
  49. def __init__(self, name, curve, generator, oid, openssl_name=None):
  50. self.name = name
  51. self.openssl_name = openssl_name # maybe None
  52. self.curve = curve
  53. self.generator = generator
  54. self.order = generator.order()
  55. if isinstance(curve, ellipticcurve.CurveEdTw):
  56. # EdDSA keys are special in that both private and public
  57. # are the same size (as it's defined only with compressed points)
  58. # +1 for the sign bit and then round up
  59. self.baselen = (bit_length(curve.p()) + 1 + 7) // 8
  60. self.verifying_key_length = self.baselen
  61. else:
  62. self.baselen = orderlen(self.order)
  63. self.verifying_key_length = 2 * orderlen(curve.p())
  64. self.signature_length = 2 * self.baselen
  65. self.oid = oid
  66. if oid:
  67. self.encoded_oid = der.encode_oid(*oid)
  68. def __eq__(self, other):
  69. if isinstance(other, Curve):
  70. return (
  71. self.curve == other.curve and self.generator == other.generator
  72. )
  73. return NotImplemented
  74. def __ne__(self, other):
  75. return not self == other
  76. def __repr__(self):
  77. return self.name
  78. def to_der(self, encoding=None, point_encoding="uncompressed"):
  79. """Serialise the curve parameters to binary string.
  80. :param str encoding: the format to save the curve parameters in.
  81. Default is ``named_curve``, with fallback being the ``explicit``
  82. if the OID is not set for the curve.
  83. :param str point_encoding: the point encoding of the generator when
  84. explicit curve encoding is used. Ignored for ``named_curve``
  85. format.
  86. :return: DER encoded ECParameters structure
  87. :rtype: bytes
  88. """
  89. if encoding is None:
  90. if self.oid:
  91. encoding = "named_curve"
  92. else:
  93. encoding = "explicit"
  94. if encoding not in ("named_curve", "explicit"):
  95. raise ValueError(
  96. "Only 'named_curve' and 'explicit' encodings supported"
  97. )
  98. if encoding == "named_curve":
  99. if not self.oid:
  100. raise UnknownCurveError(
  101. "Can't encode curve using named_curve encoding without "
  102. "associated curve OID"
  103. )
  104. return der.encode_oid(*self.oid)
  105. elif isinstance(self.curve, ellipticcurve.CurveEdTw):
  106. assert encoding == "explicit"
  107. raise UnknownCurveError(
  108. "Twisted Edwards curves don't support explicit encoding"
  109. )
  110. # encode the ECParameters sequence
  111. curve_p = self.curve.p()
  112. version = der.encode_integer(1)
  113. field_id = der.encode_sequence(
  114. der.encode_oid(*PRIME_FIELD_OID), der.encode_integer(curve_p)
  115. )
  116. curve = der.encode_sequence(
  117. der.encode_octet_string(
  118. number_to_string(self.curve.a() % curve_p, curve_p)
  119. ),
  120. der.encode_octet_string(
  121. number_to_string(self.curve.b() % curve_p, curve_p)
  122. ),
  123. )
  124. base = der.encode_octet_string(self.generator.to_bytes(point_encoding))
  125. order = der.encode_integer(self.generator.order())
  126. seq_elements = [version, field_id, curve, base, order]
  127. if self.curve.cofactor():
  128. cofactor = der.encode_integer(self.curve.cofactor())
  129. seq_elements.append(cofactor)
  130. return der.encode_sequence(*seq_elements)
  131. def to_pem(self, encoding=None, point_encoding="uncompressed"):
  132. """
  133. Serialise the curve parameters to the :term:`PEM` format.
  134. :param str encoding: the format to save the curve parameters in.
  135. Default is ``named_curve``, with fallback being the ``explicit``
  136. if the OID is not set for the curve.
  137. :param str point_encoding: the point encoding of the generator when
  138. explicit curve encoding is used. Ignored for ``named_curve``
  139. format.
  140. :return: PEM encoded ECParameters structure
  141. :rtype: str
  142. """
  143. return der.topem(
  144. self.to_der(encoding, point_encoding), "EC PARAMETERS"
  145. )
  146. @staticmethod
  147. def from_der(data, valid_encodings=None):
  148. """Decode the curve parameters from DER file.
  149. :param data: the binary string to decode the parameters from
  150. :type data: :term:`bytes-like object`
  151. :param valid_encodings: set of names of allowed encodings, by default
  152. all (set by passing ``None``), supported ones are ``named_curve``
  153. and ``explicit``
  154. :type valid_encodings: :term:`set-like object`
  155. """
  156. if not valid_encodings:
  157. valid_encodings = set(("named_curve", "explicit"))
  158. if not all(i in ["named_curve", "explicit"] for i in valid_encodings):
  159. raise ValueError(
  160. "Only named_curve and explicit encodings supported"
  161. )
  162. data = normalise_bytes(data)
  163. if not der.is_sequence(data):
  164. if "named_curve" not in valid_encodings:
  165. raise der.UnexpectedDER(
  166. "named_curve curve parameters not allowed"
  167. )
  168. oid, empty = der.remove_object(data)
  169. if empty:
  170. raise der.UnexpectedDER("Unexpected data after OID")
  171. return find_curve(oid)
  172. if "explicit" not in valid_encodings:
  173. raise der.UnexpectedDER("explicit curve parameters not allowed")
  174. seq, empty = der.remove_sequence(data)
  175. if empty:
  176. raise der.UnexpectedDER(
  177. "Unexpected data after ECParameters structure"
  178. )
  179. # decode the ECParameters sequence
  180. version, rest = der.remove_integer(seq)
  181. if version != 1:
  182. raise der.UnexpectedDER("Unknown parameter encoding format")
  183. field_id, rest = der.remove_sequence(rest)
  184. curve, rest = der.remove_sequence(rest)
  185. base_bytes, rest = der.remove_octet_string(rest)
  186. order, rest = der.remove_integer(rest)
  187. cofactor = None
  188. if rest:
  189. # the ASN.1 specification of ECParameters allows for future
  190. # extensions of the sequence, so ignore the remaining bytes
  191. cofactor, _ = der.remove_integer(rest)
  192. # decode the ECParameters.fieldID sequence
  193. field_type, rest = der.remove_object(field_id)
  194. if field_type == CHARACTERISTIC_TWO_FIELD_OID:
  195. raise UnknownCurveError("Characteristic 2 curves unsupported")
  196. if field_type != PRIME_FIELD_OID:
  197. raise UnknownCurveError(
  198. "Unknown field type: {0}".format(field_type)
  199. )
  200. prime, empty = der.remove_integer(rest)
  201. if empty:
  202. raise der.UnexpectedDER(
  203. "Unexpected data after ECParameters.fieldID.Prime-p element"
  204. )
  205. # decode the ECParameters.curve sequence
  206. curve_a_bytes, rest = der.remove_octet_string(curve)
  207. curve_b_bytes, rest = der.remove_octet_string(rest)
  208. # seed can be defined here, but we don't parse it, so ignore `rest`
  209. curve_a = string_to_number(curve_a_bytes)
  210. curve_b = string_to_number(curve_b_bytes)
  211. curve_fp = ellipticcurve.CurveFp(prime, curve_a, curve_b, cofactor)
  212. # decode the ECParameters.base point
  213. base = ellipticcurve.PointJacobi.from_bytes(
  214. curve_fp,
  215. base_bytes,
  216. valid_encodings=("uncompressed", "compressed", "hybrid"),
  217. order=order,
  218. generator=True,
  219. )
  220. tmp_curve = Curve("unknown", curve_fp, base, None)
  221. # if the curve matches one of the well-known ones, use the well-known
  222. # one in preference, as it will have the OID and name associated
  223. for i in curves:
  224. if tmp_curve == i:
  225. return i
  226. return tmp_curve
  227. @classmethod
  228. def from_pem(cls, string, valid_encodings=None):
  229. """Decode the curve parameters from PEM file.
  230. :param str string: the text string to decode the parameters from
  231. :param valid_encodings: set of names of allowed encodings, by default
  232. all (set by passing ``None``), supported ones are ``named_curve``
  233. and ``explicit``
  234. :type valid_encodings: :term:`set-like object`
  235. """
  236. if not PY2 and isinstance(string, str): # pragma: no branch
  237. string = string.encode()
  238. ec_param_index = string.find(b"-----BEGIN EC PARAMETERS-----")
  239. if ec_param_index == -1:
  240. raise der.UnexpectedDER("EC PARAMETERS PEM header not found")
  241. return cls.from_der(
  242. der.unpem(string[ec_param_index:]), valid_encodings
  243. )
  244. # the SEC curves
  245. SECP112r1 = Curve(
  246. "SECP112r1",
  247. ecdsa.curve_112r1,
  248. ecdsa.generator_112r1,
  249. (1, 3, 132, 0, 6),
  250. "secp112r1",
  251. )
  252. SECP112r2 = Curve(
  253. "SECP112r2",
  254. ecdsa.curve_112r2,
  255. ecdsa.generator_112r2,
  256. (1, 3, 132, 0, 7),
  257. "secp112r2",
  258. )
  259. SECP128r1 = Curve(
  260. "SECP128r1",
  261. ecdsa.curve_128r1,
  262. ecdsa.generator_128r1,
  263. (1, 3, 132, 0, 28),
  264. "secp128r1",
  265. )
  266. SECP160r1 = Curve(
  267. "SECP160r1",
  268. ecdsa.curve_160r1,
  269. ecdsa.generator_160r1,
  270. (1, 3, 132, 0, 8),
  271. "secp160r1",
  272. )
  273. # the NIST curves
  274. NIST192p = Curve(
  275. "NIST192p",
  276. ecdsa.curve_192,
  277. ecdsa.generator_192,
  278. (1, 2, 840, 10045, 3, 1, 1),
  279. "prime192v1",
  280. )
  281. NIST224p = Curve(
  282. "NIST224p",
  283. ecdsa.curve_224,
  284. ecdsa.generator_224,
  285. (1, 3, 132, 0, 33),
  286. "secp224r1",
  287. )
  288. NIST256p = Curve(
  289. "NIST256p",
  290. ecdsa.curve_256,
  291. ecdsa.generator_256,
  292. (1, 2, 840, 10045, 3, 1, 7),
  293. "prime256v1",
  294. )
  295. NIST384p = Curve(
  296. "NIST384p",
  297. ecdsa.curve_384,
  298. ecdsa.generator_384,
  299. (1, 3, 132, 0, 34),
  300. "secp384r1",
  301. )
  302. NIST521p = Curve(
  303. "NIST521p",
  304. ecdsa.curve_521,
  305. ecdsa.generator_521,
  306. (1, 3, 132, 0, 35),
  307. "secp521r1",
  308. )
  309. SECP256k1 = Curve(
  310. "SECP256k1",
  311. ecdsa.curve_secp256k1,
  312. ecdsa.generator_secp256k1,
  313. (1, 3, 132, 0, 10),
  314. "secp256k1",
  315. )
  316. BRAINPOOLP160r1 = Curve(
  317. "BRAINPOOLP160r1",
  318. ecdsa.curve_brainpoolp160r1,
  319. ecdsa.generator_brainpoolp160r1,
  320. (1, 3, 36, 3, 3, 2, 8, 1, 1, 1),
  321. "brainpoolP160r1",
  322. )
  323. BRAINPOOLP160t1 = Curve(
  324. "BRAINPOOLP160t1",
  325. ecdsa.curve_brainpoolp160t1,
  326. ecdsa.generator_brainpoolp160t1,
  327. (1, 3, 36, 3, 3, 2, 8, 1, 1, 2),
  328. "brainpoolP160t1",
  329. )
  330. BRAINPOOLP192r1 = Curve(
  331. "BRAINPOOLP192r1",
  332. ecdsa.curve_brainpoolp192r1,
  333. ecdsa.generator_brainpoolp192r1,
  334. (1, 3, 36, 3, 3, 2, 8, 1, 1, 3),
  335. "brainpoolP192r1",
  336. )
  337. BRAINPOOLP192t1 = Curve(
  338. "BRAINPOOLP192t1",
  339. ecdsa.curve_brainpoolp192t1,
  340. ecdsa.generator_brainpoolp192t1,
  341. (1, 3, 36, 3, 3, 2, 8, 1, 1, 4),
  342. "brainpoolP192t1",
  343. )
  344. BRAINPOOLP224r1 = Curve(
  345. "BRAINPOOLP224r1",
  346. ecdsa.curve_brainpoolp224r1,
  347. ecdsa.generator_brainpoolp224r1,
  348. (1, 3, 36, 3, 3, 2, 8, 1, 1, 5),
  349. "brainpoolP224r1",
  350. )
  351. BRAINPOOLP224t1 = Curve(
  352. "BRAINPOOLP224t1",
  353. ecdsa.curve_brainpoolp224t1,
  354. ecdsa.generator_brainpoolp224t1,
  355. (1, 3, 36, 3, 3, 2, 8, 1, 1, 6),
  356. "brainpoolP224t1",
  357. )
  358. BRAINPOOLP256r1 = Curve(
  359. "BRAINPOOLP256r1",
  360. ecdsa.curve_brainpoolp256r1,
  361. ecdsa.generator_brainpoolp256r1,
  362. (1, 3, 36, 3, 3, 2, 8, 1, 1, 7),
  363. "brainpoolP256r1",
  364. )
  365. BRAINPOOLP256t1 = Curve(
  366. "BRAINPOOLP256t1",
  367. ecdsa.curve_brainpoolp256t1,
  368. ecdsa.generator_brainpoolp256t1,
  369. (1, 3, 36, 3, 3, 2, 8, 1, 1, 8),
  370. "brainpoolP256t1",
  371. )
  372. BRAINPOOLP320r1 = Curve(
  373. "BRAINPOOLP320r1",
  374. ecdsa.curve_brainpoolp320r1,
  375. ecdsa.generator_brainpoolp320r1,
  376. (1, 3, 36, 3, 3, 2, 8, 1, 1, 9),
  377. "brainpoolP320r1",
  378. )
  379. BRAINPOOLP320t1 = Curve(
  380. "BRAINPOOLP320t1",
  381. ecdsa.curve_brainpoolp320t1,
  382. ecdsa.generator_brainpoolp320t1,
  383. (1, 3, 36, 3, 3, 2, 8, 1, 1, 10),
  384. "brainpoolP320t1",
  385. )
  386. BRAINPOOLP384r1 = Curve(
  387. "BRAINPOOLP384r1",
  388. ecdsa.curve_brainpoolp384r1,
  389. ecdsa.generator_brainpoolp384r1,
  390. (1, 3, 36, 3, 3, 2, 8, 1, 1, 11),
  391. "brainpoolP384r1",
  392. )
  393. BRAINPOOLP384t1 = Curve(
  394. "BRAINPOOLP384t1",
  395. ecdsa.curve_brainpoolp384t1,
  396. ecdsa.generator_brainpoolp384t1,
  397. (1, 3, 36, 3, 3, 2, 8, 1, 1, 12),
  398. "brainpoolP384t1",
  399. )
  400. BRAINPOOLP512r1 = Curve(
  401. "BRAINPOOLP512r1",
  402. ecdsa.curve_brainpoolp512r1,
  403. ecdsa.generator_brainpoolp512r1,
  404. (1, 3, 36, 3, 3, 2, 8, 1, 1, 13),
  405. "brainpoolP512r1",
  406. )
  407. BRAINPOOLP512t1 = Curve(
  408. "BRAINPOOLP512t1",
  409. ecdsa.curve_brainpoolp512t1,
  410. ecdsa.generator_brainpoolp512t1,
  411. (1, 3, 36, 3, 3, 2, 8, 1, 1, 14),
  412. "brainpoolP512t1",
  413. )
  414. Ed25519 = Curve(
  415. "Ed25519",
  416. eddsa.curve_ed25519,
  417. eddsa.generator_ed25519,
  418. (1, 3, 101, 112),
  419. )
  420. Ed448 = Curve(
  421. "Ed448",
  422. eddsa.curve_ed448,
  423. eddsa.generator_ed448,
  424. (1, 3, 101, 113),
  425. )
  426. # no order in particular, but keep previously added curves first
  427. curves = [
  428. NIST192p,
  429. NIST224p,
  430. NIST256p,
  431. NIST384p,
  432. NIST521p,
  433. SECP256k1,
  434. BRAINPOOLP160r1,
  435. BRAINPOOLP192r1,
  436. BRAINPOOLP224r1,
  437. BRAINPOOLP256r1,
  438. BRAINPOOLP320r1,
  439. BRAINPOOLP384r1,
  440. BRAINPOOLP512r1,
  441. SECP112r1,
  442. SECP112r2,
  443. SECP128r1,
  444. SECP160r1,
  445. Ed25519,
  446. Ed448,
  447. BRAINPOOLP160t1,
  448. BRAINPOOLP192t1,
  449. BRAINPOOLP224t1,
  450. BRAINPOOLP256t1,
  451. BRAINPOOLP320t1,
  452. BRAINPOOLP384t1,
  453. BRAINPOOLP512t1,
  454. ]
  455. def find_curve(oid_curve):
  456. """Select a curve based on its OID
  457. :param tuple[int,...] oid_curve: ASN.1 Object Identifier of the
  458. curve to return, like ``(1, 2, 840, 10045, 3, 1, 7)`` for ``NIST256p``.
  459. :raises UnknownCurveError: When the oid doesn't match any of the supported
  460. curves
  461. :rtype: ~ecdsa.curves.Curve
  462. """
  463. for c in curves:
  464. if c.oid == oid_curve:
  465. return c
  466. raise UnknownCurveError(
  467. "I don't know about the curve with oid %s."
  468. "I only know about these: %s" % (oid_curve, [c.name for c in curves])
  469. )
  470. def curve_by_name(name):
  471. """Select a curve based on its name.
  472. Returns a :py:class:`~ecdsa.curves.Curve` object with a ``name`` name.
  473. Note that ``name`` is case-sensitve.
  474. :param str name: Name of the curve to return, like ``NIST256p`` or
  475. ``prime256v1``
  476. :raises UnknownCurveError: When the name doesn't match any of the supported
  477. curves
  478. :rtype: ~ecdsa.curves.Curve
  479. """
  480. for c in curves:
  481. if name == c.name or (c.openssl_name and name == c.openssl_name):
  482. return c
  483. raise UnknownCurveError(
  484. "Curve with name {0!r} unknown, only curves supported: {1}".format(
  485. name, [c.name for c in curves]
  486. )
  487. )