_montgomery.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. # This file is licensed under the BSD 2-Clause License.
  2. # See https://opensource.org/licenses/BSD-2-Clause for details.
  3. from ._curve import _Curve
  4. from Crypto.Math.Numbers import Integer
  5. from Crypto.Util._raw_api import (load_pycryptodome_raw_lib, VoidPointer,
  6. SmartPointer)
  7. def curve25519_curve():
  8. p = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed # 2**255 - 19
  9. order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
  10. _curve25519_lib = load_pycryptodome_raw_lib("Crypto.PublicKey._curve25519", """
  11. typedef void Point;
  12. int curve25519_new_point(Point **out,
  13. const uint8_t x[32],
  14. size_t modsize,
  15. const void* context);
  16. int curve25519_clone(Point **P, const Point *Q);
  17. void curve25519_free_point(Point *p);
  18. int curve25519_get_x(uint8_t *xb, size_t modsize, Point *p);
  19. int curve25519_scalar(Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed);
  20. int curve25519_cmp(const Point *ecp1, const Point *ecp2);
  21. """)
  22. class EcLib(object):
  23. new_point = _curve25519_lib.curve25519_new_point
  24. clone = _curve25519_lib.curve25519_clone
  25. free_point = _curve25519_lib.curve25519_free_point
  26. get_x = _curve25519_lib.curve25519_get_x
  27. scalar = _curve25519_lib.curve25519_scalar
  28. cmp = _curve25519_lib.curve25519_cmp
  29. def _validate_x25519_point(point):
  30. p2 = p * 2
  31. x1 = 325606250916557431795983626356110631294008115727848805560023387167927233504
  32. x2 = 39382357235489614581723060781553021112529911719440698176882885853963445705823
  33. # http://cr.yp.to/ecdh.html#validate
  34. deny_list = (
  35. 0,
  36. 1,
  37. x1,
  38. x2,
  39. p - 1,
  40. p,
  41. p + 1,
  42. p + x1,
  43. p + x2,
  44. p2 - 1,
  45. p2,
  46. p2 + 1,
  47. )
  48. try:
  49. valid = point.x not in deny_list
  50. except ValueError:
  51. valid = False
  52. if not valid:
  53. raise ValueError("Invalid Curve25519 public key")
  54. curve25519 = _Curve(Integer(p),
  55. None,
  56. Integer(order),
  57. Integer(9),
  58. None,
  59. None,
  60. 255,
  61. "1.3.101.110", # RFC8410
  62. None,
  63. "Curve25519",
  64. None,
  65. EcLib,
  66. _validate_x25519_point,
  67. )
  68. return curve25519
  69. def curve448_curve():
  70. p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffff # 2**448 - 2**224 - 1
  71. order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3
  72. _curve448_lib = load_pycryptodome_raw_lib("Crypto.PublicKey._curve448", """
  73. typedef void Curve448Context;
  74. typedef void Curve448Point;
  75. int curve448_new_context(Curve448Context **pec_ctx);
  76. void curve448_free_context(Curve448Context *ec_ctx);
  77. int curve448_new_point(Curve448Point **out,
  78. const uint8_t *x,
  79. size_t len,
  80. const Curve448Context *ec_ctx);
  81. void curve448_free_point(Curve448Point *p);
  82. int curve448_clone(Curve448Point **P, const Curve448Point *Q);
  83. int curve448_get_x(uint8_t *xb, size_t modsize, const Curve448Point *p);
  84. int curve448_scalar(Curve448Point *P, const uint8_t *scalar, size_t scalar_len, uint64_t seed);
  85. int curve448_cmp(const Curve448Point *ecp1, const Curve448Point *ecp2);
  86. """)
  87. class EcLib(object):
  88. new_context = _curve448_lib.curve448_new_context
  89. free_context = _curve448_lib.curve448_free_context
  90. new_point = _curve448_lib.curve448_new_point
  91. clone = _curve448_lib.curve448_clone
  92. free_point = _curve448_lib.curve448_free_point
  93. get_x = _curve448_lib.curve448_get_x
  94. scalar = _curve448_lib.curve448_scalar
  95. cmp = _curve448_lib.curve448_cmp
  96. curve448_context = VoidPointer()
  97. result = EcLib.new_context(curve448_context.address_of())
  98. if result:
  99. raise ImportError("Error %d initializing Curve448 context" % result)
  100. def _validate_x448_point(point):
  101. deny_list = (
  102. 0,
  103. 1,
  104. p - 1,
  105. p,
  106. p + 1,
  107. )
  108. try:
  109. valid = point.x not in deny_list
  110. except ValueError:
  111. valid = False
  112. if not valid:
  113. raise ValueError("Invalid Curve448 public key")
  114. curve448 = _Curve(Integer(p),
  115. None,
  116. Integer(order),
  117. Integer(5),
  118. None,
  119. None,
  120. 448,
  121. "1.3.101.111", # RFC8410
  122. SmartPointer(curve448_context.get(), EcLib.free_context),
  123. "Curve448",
  124. None,
  125. EcLib,
  126. _validate_x448_point,
  127. )
  128. return curve448