예제 #1
0
 public function _doCompressionConsistence(MathAdapterInterface $adapter, NumberTheory $theory)
 {
     foreach ($this->compression_data as $o) {
         // Try and regenerate the y coordinate from the parity byte
         // '04' . $x_coordinate . determined y coordinate should equal $o->decompressed
         // Tests squareRootModP which touches most functions in NumberTheory
         $y_byte = substr($o->compressed, 0, 2);
         $x_coordinate = substr($o->compressed, 2);
         $x = $adapter->hexDec($x_coordinate);
         // x^3
         $x3 = $adapter->powmod($x, 3, $this->generator->getCurve()->getPrime());
         // y^2
         $y2 = $adapter->add($x3, $this->generator->getCurve()->getB());
         // y0 = sqrt(y^2)
         $y0 = $theory->squareRootModP($y2, $this->generator->getCurve()->getPrime());
         if ($y_byte == '02') {
             $y_coordinate = $adapter->mod($y0, 2) == '0' ? gmp_strval(gmp_init($y0, 10), 16) : gmp_strval(gmp_sub($this->generator->getCurve()->getPrime(), $y0), 16);
         } else {
             $y_coordinate = $adapter->mod($y0, 2) == '0' ? gmp_strval(gmp_sub($this->generator->getCurve()->getPrime(), $y0), 16) : gmp_strval(gmp_init($y0, 10), 16);
         }
         $y_coordinate = str_pad($y_coordinate, 64, '0', STR_PAD_LEFT);
         // Successfully regenerated uncompressed ECDSA key from the x coordinate and the parity byte.
         $this->assertTrue('04' . $x_coordinate . $y_coordinate == $o->decompressed);
     }
 }
예제 #2
0
 /**
  * Initialize a new instance.
  *
  * @param  MathAdapterInterface $adapter
  * @param  GeneratorPoint       $generator
  * @param  PointInterface       $point
  * @throws \LogicException
  * @throws \RuntimeException
  */
 public function __construct(MathAdapterInterface $adapter, GeneratorPoint $generator, PointInterface $point)
 {
     $this->curve = $generator->getCurve();
     $this->generator = $generator;
     $this->point = $point;
     $this->adapter = $adapter;
     $n = $generator->getOrder();
     if ($n == null) {
         throw new \LogicException("Generator must have order.");
     }
     if (!$point->mul($n)->isInfinity()) {
         throw new \RuntimeException("Generator point order is bad.");
     }
     if ($adapter->cmp($point->getX(), 0) < 0 || $adapter->cmp($n, $point->getX()) <= 0 || $adapter->cmp($point->getY(), 0) < 0 || $adapter->cmp($n, $point->getY()) <= 0) {
         throw new \RuntimeException("Generator point has x and y out of range.");
     }
 }
예제 #3
0
 /**
  * {@inheritDoc}
  * @see \Mdanter\Ecc\Crypto\Key\PrivateKeyInterface::getCurve()
  */
 public function getCurve()
 {
     return $this->generator->getCurve();
 }
예제 #4
0
 /**
  * Take X, Y, and a generator point, and we can get what we need!
  *
  * @param Math $math
  * @param GeneratorPoint $generator
  * @param int|string $x
  * @param int|string $y
  */
 public function __construct(Math $math, GeneratorPoint $generator, $x, $y)
 {
     parent::__construct($math, $generator->getCurve(), $x, $y, $generator->getOrder());
 }
예제 #5
0
파일: Parser.php 프로젝트: sbwdlihao/phpecc
 public function parseKey(GeneratorPoint $generator, $data)
 {
     $point = $this->pointSerializer->unserialize($generator->getCurve(), $data);
     return new PublicKey($this->adapter, $generator, $point);
 }
예제 #6
0
 /**
  * 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;
 }