EdwardsCurve.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. namespace Elliptic\Curve;
  3. use Elliptic\Curve\EdwardsCurve\Point;
  4. use Elliptic\Utils;
  5. use BN\BN;
  6. class EdwardsCurve extends BaseCurve
  7. {
  8. public $twisted;
  9. public $mOneA;
  10. public $extended;
  11. public $a;
  12. public $c;
  13. public $c2;
  14. public $d;
  15. public $d2;
  16. public $dd;
  17. public $oneC;
  18. function __construct($conf)
  19. {
  20. // NOTE: Important as we are creating point in Base.call()
  21. $this->twisted = ($conf["a"] | 0) != 1;
  22. $this->mOneA = $this->twisted && ($conf["a"] | 0) == -1;
  23. $this->extended = $this->mOneA;
  24. parent::__construct("edward", $conf);
  25. $this->a = (new BN($conf["a"], 16))->umod($this->red->m);
  26. $this->a = $this->a->toRed($this->red);
  27. $this->c = (new BN($conf["c"], 16))->toRed($this->red);
  28. $this->c2 = $this->c->redSqr();
  29. $this->d = (new BN($conf["d"], 16))->toRed($this->red);
  30. $this->dd = $this->d->redAdd($this->d);
  31. if (Utils::$ASSERT_ENABLED) {
  32. assert(!$this->twisted || $this->c->fromRed()->cmpn(1) == 0);
  33. }
  34. $this->oneC = ($conf["c"] | 0) == 1;
  35. }
  36. public function _mulA($num) {
  37. if ($this->mOneA)
  38. return $num->redNeg();
  39. else
  40. return $this->a->redMul($num);
  41. }
  42. public function _mulC($num) {
  43. if ($this->oneC)
  44. return $num;
  45. else
  46. return $this->c->redMul($num);
  47. }
  48. // Just for compatibility with Short curve
  49. public function jpoint($x, $y, $z, $t = null) {
  50. return $this->point($x, $y, $z, $t);
  51. }
  52. public function pointFromX($x, $odd = false) {
  53. $x = new BN($x, 16);
  54. if (!$x->red)
  55. $x = $x->toRed($this->red);
  56. $x2 = $x->redSqr();
  57. $rhs = $this->c2->redSub($this->a->redMul($x2));
  58. $lhs = $this->one->redSub($this->c2->redMul($this->d)->redMul($x2));
  59. $y2 = $rhs->redMul($lhs->redInvm());
  60. $y = $y2->redSqrt();
  61. if ($y->redSqr()->redSub($y2)->cmp($this->zero) != 0)
  62. throw new \Exception('invalid point');
  63. $isOdd = $y->fromRed()->isOdd();
  64. if ($odd && !$isOdd || !$odd && $isOdd)
  65. $y = $y->redNeg();
  66. return $this->point($x, $y);
  67. }
  68. public function pointFromY($y, $odd = false) {
  69. $y = new BN($y, 16);
  70. if (!$y->red)
  71. $y = $y->toRed($this->red);
  72. // x^2 = (y^2 - 1) / (d y^2 + 1)
  73. $y2 = $y->redSqr();
  74. $lhs = $y2->redSub($this->one);
  75. $rhs = $y2->redMul($this->d)->redAdd($this->one);
  76. $x2 = $lhs->redMul($rhs->redInvm());
  77. if ($x2->cmp($this->zero) == 0) {
  78. if ($odd)
  79. throw new \Exception('invalid point');
  80. else
  81. return $this->point($this->zero, $y);
  82. }
  83. $x = $x2->redSqrt();
  84. if ($x->redSqr()->redSub($x2)->cmp($this->zero) != 0)
  85. throw new \Exception('invalid point');
  86. if ($x->isOdd() != $odd)
  87. $x = $x->redNeg();
  88. return $this->point($x, $y);
  89. }
  90. public function validate($point) {
  91. if ($point->isInfinity())
  92. return true;
  93. // Curve: A * X^2 + Y^2 = C^2 * (1 + D * X^2 * Y^2)
  94. $point->normalize();
  95. $x2 = $point->x->redSqr();
  96. $y2 = $point->y->redSqr();
  97. $lhs = $x2->redMul($this->a)->redAdd($y2);
  98. $rhs = $this->c2->redMul($this->one->redAdd($this->d->redMul($x2)->redMul($y2)));
  99. return $lhs->cmp($rhs) == 0;
  100. }
  101. public function pointFromJSON($obj) {
  102. return Point::fromJSON($this, $obj);
  103. }
  104. public function point($x = null, $y = null, $z = null, $t = null) {
  105. return new Point($this, $x, $y, $z, $t);
  106. }
  107. }