/** * {@inheritDoc} * @see \Mdanter\Ecc\EcMathInterface::add() */ public function add($addend) { $type = $this->identify($addend); if ($this->dataType == 'point' && $type == 'point') { $this->data = $this->data->add($addend); return $this; } if ($this->dataType == 'int' && $type == 'int') { $this->data = $this->modMath->add($this->data, $addend); return $this; } $this->handleOppositeTypes($addend, function (PointInterface $data, $addendInt) { // Multiply by generator and return a regular point to add to $data $point = $this->generator->mul($addendInt); //$point = $this->generator->getCurve()->getPoint($point->getX(), $point->getY(), $this->generator->getOrder()); return $data->add($point); }); return $this; }
/** * {@inheritDoc} * @see \Mdanter\Ecc\Crypto\Key\PrivateKeyInterface::getPublicKey() */ public function getPublicKey() { return new PublicKey($this->adapter, $this->generator, $this->generator->mul($this->secretMultiplier)); }
/** * based on php-bitcoin-signature-routines implementation (which is based on bitcoinjs-lib's implementation) * which is SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public Key Recovery Operation" * http://www.secg.org/sec1-v2.pdf * * @param $r * @param $s * @param $e * @param $recoveryFlags * @param GeneratorPoint $G * @return bool|PublicKey */ private static function recoverPubKey($r, $s, $e, $recoveryFlags, GeneratorPoint $G) { $math = EccFactory::getAdapter(); $isYEven = ($recoveryFlags & 1) != 0; $isSecondKey = ($recoveryFlags & 2) != 0; $curve = $G->getCurve(); $signature = new Signature($r, $s); // Precalculate (p + 1) / 4 where p is the field order $p_over_four = $math->div($math->add($curve->getPrime(), 1), 4); // 1.1 Compute x if (!$isSecondKey) { $x = $r; } else { $x = $math->add($r, $G->getOrder()); } // 1.3 Convert x to point $alpha = $math->mod($math->add($math->add($math->pow($x, 3), $math->mul($curve->getA(), $x)), $curve->getB()), $curve->getPrime()); $beta = $math->powmod($alpha, $p_over_four, $curve->getPrime()); // If beta is even, but y isn't or vice versa, then convert it, // otherwise we're done and y == beta. if (($math->mod($beta, 2) == 0) == $isYEven) { $y = $math->sub($curve->getPrime(), $beta); } else { $y = $beta; } // 1.4 Check that nR is at infinity (implicitly done in constructor) $R = $G->getCurve()->getPoint($x, $y); $point_negate = function (PointInterface $p) use($math, $G) { return $G->getCurve()->getPoint($p->getX(), $math->mul($p->getY(), -1)); }; // 1.6.1 Compute a candidate public key Q = r^-1 (sR - eG) $rInv = $math->inverseMod($r, $G->getOrder()); $eGNeg = $point_negate($G->mul($e)); $Q = $R->mul($s)->add($eGNeg)->mul($rInv); // 1.6.2 Test Q as a public key $signer = new Signer($math); $Qk = new PublicKey($math, $G, $Q); if ($signer->verify($Qk, $signature, $e)) { return $Qk; } return false; }