Point.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. namespace Elliptic\Curve\EdwardsCurve;
  3. use BN\BN;
  4. class Point extends \Elliptic\Curve\BaseCurve\Point
  5. {
  6. public $x;
  7. public $y;
  8. public $z;
  9. public $t;
  10. public $zOne;
  11. function __construct($curve, $x = null, $y = null, $z = null, $t = null) {
  12. parent::__construct($curve, 'projective');
  13. if ($x == null && $y == null && $z == null) {
  14. $this->x = $this->curve->zero;
  15. $this->y = $this->curve->one;
  16. $this->z = $this->curve->one;
  17. $this->t = $this->curve->zero;
  18. $this->zOne = true;
  19. } else {
  20. $this->x = new BN($x, 16);
  21. $this->y = new BN($y, 16);
  22. $this->z = $z ? new BN($z, 16) : $this->curve->one;
  23. $this->t = $t ? new BN($t, 16) : null;
  24. if (!$this->x->red)
  25. $this->x = $this->x->toRed($this->curve->red);
  26. if (!$this->y->red)
  27. $this->y = $this->y->toRed($this->curve->red);
  28. if (!$this->z->red)
  29. $this->z = $this->z->toRed($this->curve->red);
  30. if ($this->t && !$this->t->red)
  31. $this->t = $this->t->toRed($this->curve->red);
  32. $this->zOne = $this->z == $this->curve->one;
  33. // Use extended coordinates
  34. if ($this->curve->extended && !$this->t) {
  35. $this->t = $this->x->redMul($this->y);
  36. if (!$this->zOne)
  37. $this->t = $this->t->redMul($this->z->redInvm());
  38. }
  39. }
  40. }
  41. public static function fromJSON($curve, $obj) {
  42. return new Point($curve,
  43. isset($obj[0]) ? $obj[0] : null,
  44. isset($obj[1]) ? $obj[1] : null,
  45. isset($obj[2]) ? $obj[2] : null
  46. );
  47. }
  48. public function inspect() {
  49. if ($this->isInfinity())
  50. return '<EC Point Infinity>';
  51. return '<EC Point x: ' . $this->x->fromRed()->toString(16, 2) .
  52. ' y: ' . $this->y->fromRed()->toString(16, 2) .
  53. ' z: ' . $this->z->fromRed()->toString(16, 2) . '>';
  54. }
  55. public function isInfinity() {
  56. // XXX This code assumes that zero is always zero in red
  57. return $this->x->cmpn(0) == 0 &&
  58. $this->y->cmp($this->z) == 0;
  59. }
  60. public function _extDbl() {
  61. // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  62. // #doubling-dbl-2008-hwcd
  63. // 4M + 4S
  64. // A = X1^2
  65. $a = $this->x->redSqr();
  66. // B = Y1^2
  67. $b = $this->y->redSqr();
  68. // C = 2 * Z1^2
  69. $c = $this->z->redSqr();
  70. $c = $c->redIAdd($c);
  71. // D = a * A
  72. $d = $this->curve->_mulA($a);
  73. // E = (X1 + Y1)^2 - A - B
  74. $e = $this->x->redAdd($this->y)->redSqr()->redISub($a)->redISub($b);
  75. // G = D + B
  76. $g = $d->redAdd($b);
  77. // F = G - C
  78. $f = $g->redSub($c);
  79. // H = D - B
  80. $h = $d->redSub($b);
  81. // X3 = E * F
  82. $nx = $e->redMul($f);
  83. // Y3 = G * H
  84. $ny = $g->redMul($h);
  85. // T3 = E * H
  86. $nt = $e->redMul($h);
  87. // Z3 = F * G
  88. $nz = $f->redMul($g);
  89. return $this->curve->point($nx, $ny, $nz, $nt);
  90. }
  91. public function _projDbl() {
  92. // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
  93. // #doubling-dbl-2008-bbjlp
  94. // #doubling-dbl-2007-bl
  95. // and others
  96. // Generally 3M + 4S or 2M + 4S
  97. // B = (X1 + Y1)^2
  98. $b = $this->x->redAdd($this->y)->redSqr();
  99. // C = X1^2
  100. $c = $this->x->redSqr();
  101. // D = Y1^2
  102. $d = $this->y->redSqr();
  103. if ($this->curve->twisted) {
  104. // E = a * C
  105. $e = $this->curve->_mulA($c);
  106. // F = E + D
  107. $f = $e->redAdd($d);
  108. if ($this->zOne) {
  109. // X3 = (B - C - D) * (F - 2)
  110. $nx = $b->redSub($c)->redSub($d)->redMul($f->redSub($this->curve->two));
  111. // Y3 = F * (E - D)
  112. $ny = $f->redMul($e->redSub($d));
  113. // Z3 = F^2 - 2 * F
  114. $nz = $f->redSqr()->redSub($f)->redSub($f);
  115. } else {
  116. // H = Z1^2
  117. $h = $this->z->redSqr();
  118. // J = F - 2 * H
  119. $j = $f->redSub($h)->redISub($h);
  120. // X3 = (B-C-D)*J
  121. $nx = $b->redSub($c)->redISub($d)->redMul($j);
  122. // Y3 = F * (E - D)
  123. $ny = $f->redMul($e->redSub($d));
  124. // Z3 = F * J
  125. $nz = $f->redMul($j);
  126. }
  127. } else {
  128. // E = C + D
  129. $e = $c->redAdd($d);
  130. // H = (c * Z1)^2
  131. $h = $this->curve->_mulC($this->c->redMul($this->z))->redSqr();
  132. // J = E - 2 * H
  133. $j = $e->redSub($h)->redSub($h);
  134. // X3 = c * (B - E) * J
  135. $nx = $this->curve->_mulC($b->redISub($e))->redMul($j);
  136. // Y3 = c * E * (C - D)
  137. $ny = $this->curve->_mulC($e)->redMul($c->redISub($d));
  138. // Z3 = E * J
  139. $nz = $e->redMul($j);
  140. }
  141. return $this->curve->point($nx, $ny, $nz);
  142. }
  143. public function dbl() {
  144. if ($this->isInfinity())
  145. return $this;
  146. // Double in extended coordinates
  147. if ($this->curve->extended)
  148. return $this->_extDbl();
  149. else
  150. return $this->_projDbl();
  151. }
  152. public function _extAdd($p) {
  153. // hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html
  154. // #addition-add-2008-hwcd-3
  155. // 8M
  156. // A = (Y1 - X1) * (Y2 - X2)
  157. $a = $this->y->redSub($this->x)->redMul($p->y->redSub($p->x));
  158. // B = (Y1 + X1) * (Y2 + X2)
  159. $b = $this->y->redAdd($this->x)->redMul($p->y->redAdd($p->x));
  160. // C = T1 * k * T2
  161. $c = $this->t->redMul($this->curve->dd)->redMul($p->t);
  162. // D = Z1 * 2 * Z2
  163. $d = $this->z->redMul($p->z->redAdd($p->z));
  164. // E = B - A
  165. $e = $b->redSub($a);
  166. // F = D - C
  167. $f = $d->redSub($c);
  168. // G = D + C
  169. $g = $d->redAdd($c);
  170. // H = B + A
  171. $h = $b->redAdd($a);
  172. // X3 = E * F
  173. $nx = $e->redMul($f);
  174. // Y3 = G * H
  175. $ny = $g->redMul($h);
  176. // T3 = E * H
  177. $nt = $e->redMul($h);
  178. // Z3 = F * G
  179. $nz = $f->redMul($g);
  180. return $this->curve->point($nx, $ny, $nz, $nt);
  181. }
  182. public function _projAdd($p) {
  183. // hyperelliptic.org/EFD/g1p/auto-twisted-projective.html
  184. // #addition-add-2008-bbjlp
  185. // #addition-add-2007-bl
  186. // 10M + 1S
  187. // A = Z1 * Z2
  188. $a = $this->z->redMul($p->z);
  189. // B = A^2
  190. $b = $a->redSqr();
  191. // C = X1 * X2
  192. $c = $this->x->redMul($p->x);
  193. // D = Y1 * Y2
  194. $d = $this->y->redMul($p->y);
  195. // E = d * C * D
  196. $e = $this->curve->d->redMul($c)->redMul($d);
  197. // F = B - E
  198. $f = $b->redSub($e);
  199. // G = B + E
  200. $g = $b->redAdd($e);
  201. // X3 = A * F * ((X1 + Y1) * (X2 + Y2) - C - D)
  202. $tmp = $this->x->redAdd($this->y)->redMul($p->x->redAdd($p->y))->redISub($c)->redISub($d);
  203. $nx = $a->redMul($f)->redMul($tmp);
  204. if ($this->curve->twisted) {
  205. // Y3 = A * G * (D - a * C)
  206. $ny = $a->redMul($g)->redMul($d->redSub($this->curve->_mulA($c)));
  207. // Z3 = F * G
  208. $nz = $f->redMul($g);
  209. } else {
  210. // Y3 = A * G * (D - C)
  211. $ny = $a->redMul($g)->redMul($d->redSub($c));
  212. // Z3 = c * F * G
  213. $nz = $this->curve->_mulC($f)->redMul($g);
  214. }
  215. return $this->curve->point($nx, $ny, $nz);
  216. }
  217. public function add($p) {
  218. if ($this->isInfinity())
  219. return $p;
  220. if ($p->isInfinity())
  221. return $this;
  222. if ($this->curve->extended)
  223. return $this->_extAdd($p);
  224. else
  225. return $this->_projAdd($p);
  226. }
  227. public function mul($k) {
  228. if ($this->_hasDoubles($k))
  229. return $this->curve->_fixedNafMul($this, $k);
  230. else
  231. return $this->curve->_wnafMul($this, $k);
  232. }
  233. public function mulAdd($k1, $p, $k2) {
  234. return $this->curve->_wnafMulAdd(1, [ $this, $p ], [ $k1, $k2 ], 2, false);
  235. }
  236. public function jmulAdd($k1, $p, $k2) {
  237. return $this->curve->_wnafMulAdd(1, [ $this, $p ], [ $k1, $k2 ], 2, true);
  238. }
  239. public function normalize() {
  240. if ($this->zOne)
  241. return $this;
  242. // Normalize coordinates
  243. $zi = $this->z->redInvm();
  244. $this->x = $this->x->redMul($zi);
  245. $this->y = $this->y->redMul($zi);
  246. if ($this->t)
  247. $this->t = $this->t->redMul($zi);
  248. $this->z = $this->curve->one;
  249. $this->zOne = true;
  250. return $this;
  251. }
  252. public function neg() {
  253. return $this->curve->point($this->x->redNeg(),
  254. $this->y,
  255. $this->z,
  256. ($this->t != null) ? $this->t->redNeg() : null);
  257. }
  258. public function getX() {
  259. $this->normalize();
  260. return $this->x->fromRed();
  261. }
  262. public function getY() {
  263. $this->normalize();
  264. return $this->y->fromRed();
  265. }
  266. public function eq($other) {
  267. return $this == $other ||
  268. $this->getX()->cmp($other->getX()) == 0 &&
  269. $this->getY()->cmp($other->getY()) == 0;
  270. }
  271. public function eqXToP($x) {
  272. $rx = $x->toRed($this->curve->red)->redMul($this->z);
  273. if ($this->x->cmp($rx) == 0)
  274. return true;
  275. $xc = $x->_clone();
  276. $t = $this->curve->redN->redMul($this->z);
  277. for (;;) {
  278. $xc->iadd($this->curve->n);
  279. if ($xc->cmp($this->curve->p) >= 0)
  280. return false;
  281. $rx->redIAdd($t);
  282. if ($this->x->cmp($rx) == 0)
  283. return true;
  284. }
  285. return false;
  286. }
  287. // Compatibility with BaseCurve
  288. public function toP() { return $this->normalize(); }
  289. public function mixedAdd($p) { return $this->add($p); }
  290. }