Point.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <?php
  2. namespace Elliptic\Curve\MontCurve;
  3. use BN\BN;
  4. class Point extends \Elliptic\Curve\BaseCurve\Point
  5. {
  6. public $x;
  7. public $z;
  8. function __construct($curve, $x, $z)
  9. {
  10. parent::__construct($curve, "projective");
  11. if( $x == null && $z == null )
  12. {
  13. $this->x = $this->curve->one;
  14. $this->z = $this->curve->zero;
  15. }
  16. else
  17. {
  18. $this->x = new BN($x, 16);
  19. $this->z = new BN($z, 16);
  20. if( !$this->x->red )
  21. $this->x = $this->x->toRed($this->curve->red);
  22. if( !$this->z->red )
  23. $this->z = $this->z->toRed($this->curve->red);
  24. }
  25. }
  26. public function precompute($power = null) {
  27. // No-op
  28. }
  29. protected function _encode($compact) {
  30. return $this->getX()->toArray("be", $this->curve->p->byteLength());
  31. }
  32. public static function fromJSON($curve, $obj) {
  33. return new Point($curve, $obj[0], isset($obj[1]) ? $obj[1] : $curve->one);
  34. }
  35. public function inspect()
  36. {
  37. if( $this->isInfinity() )
  38. return "<EC Point Infinity>";
  39. return "<EC Point x: " . $this->x->fromRed()->toString(16, 2) .
  40. " z: " . $this->z->fromRed()->toString(16, 2) . ">";
  41. }
  42. public function isInfinity() {
  43. // XXX This code assumes that zero is always zero in red
  44. return $this->z->isZero();
  45. }
  46. public function dbl()
  47. {
  48. // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#doubling-dbl-1987-m-3
  49. // 2M + 2S + 4A
  50. // A = X1 + Z1
  51. $a = $this->x->redAdd($this->z);
  52. // AA = A^2
  53. $aa = $a->redSqr();
  54. // B = X1 - Z1
  55. $b = $this->x->redSub($this->z);
  56. // BB = B^2
  57. $bb = $b->redSqr();
  58. // C = AA - BB
  59. $c = $aa->redSub($bb);
  60. // X3 = AA * BB
  61. $nx = $aa->redMul($bb);
  62. // Z3 = C * (BB + A24 * C)
  63. $nz = $c->redMul( $bb->redAdd($this->curve->a24->redMul($c)) );
  64. return $this->curve->point($nx, $nz);
  65. }
  66. public function add($p) {
  67. throw new \Exception('Not supported on Montgomery curve');
  68. }
  69. public function diffAdd($p, $diff)
  70. {
  71. // http://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html#diffadd-dadd-1987-m-3
  72. // 4M + 2S + 6A
  73. // A = X2 + Z2
  74. $a = $this->x->redAdd($this->z);
  75. // B = X2 - Z2
  76. $b = $this->x->redSub($this->z);
  77. // C = X3 + Z3
  78. $c = $p->x->redAdd($p->z);
  79. // D = X3 - Z3
  80. $d = $p->x->redSub($p->z);
  81. // DA = D * A
  82. $da = $d->redMul($a);
  83. // CB = C * B
  84. $cb = $c->redMul($b);
  85. // X5 = Z1 * (DA + CB)^2
  86. $nx = $diff->z->redMul($da->redAdd($cb)->redSqr());
  87. // Z5 = X1 * (DA - CB)^2
  88. $nz = $diff->x->redMul($da->redSub($cb)->redSqr());
  89. return $this->curve->point($nx, $nz);
  90. }
  91. public function mul($k)
  92. {
  93. $t = $k->_clone();
  94. $a = $this; // (N / 2) * Q + Q
  95. $b = $this->curve->point(null, null); // (N / 2) * Q
  96. $c = $this; // Q
  97. $bits = array();
  98. while( !$t->isZero() )
  99. {
  100. // TODO: Maybe it is faster to use toString(2)?
  101. array_push($bits, $t->andln(1));
  102. $t->iushrn(1);
  103. }
  104. for($i = count($bits) - 1; $i >= 0; $i--)
  105. {
  106. if( $bits[$i] === 0 )
  107. {
  108. // N * Q + Q = ((N / 2) * Q + Q)) + (N / 2) * Q
  109. $a = $a->diffAdd($b, $c);
  110. // N * Q = 2 * ((N / 2) * Q + Q))
  111. $b = $b->dbl();
  112. }
  113. else
  114. {
  115. // N * Q = ((N / 2) * Q + Q) + ((N / 2) * Q)
  116. $b = $a->diffAdd($b, $c);
  117. // N * Q + Q = 2 * ((N / 2) * Q + Q)
  118. $a = $a->dbl();
  119. }
  120. }
  121. return $b;
  122. }
  123. public function eq($other) {
  124. return $this->getX()->cmp($other->getX()) === 0;
  125. }
  126. public function normalize()
  127. {
  128. $this->x = $this->x->redMul($this->z->redInvm());
  129. $this->z = $this->curve->one;
  130. return $this;
  131. }
  132. public function getX() {
  133. $this->normalize();
  134. return $this->x->fromRed();
  135. }
  136. }
  137. ?>