Пример #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
 /**
  * @param NamedCurveFp $c
  * @param GeneratorPoint $G
  * @return string
  */
 public function serialize(NamedCurveFp $c, GeneratorPoint $G)
 {
     $math = $G->getAdapter();
     $fieldID = $this->getFieldIdAsn($math, $c);
     $curve = $this->getCurveAsn($math, $c);
     $domain = new Sequence(new Integer(1), $fieldID, $curve, new OctetString($this->pointSerializer->serialize($G)), new Integer($G->getOrder()), new Integer(1));
     $payload = $domain->getBinary();
     $content = self::HEADER . PHP_EOL . trim(chunk_split(base64_encode($payload), 64, PHP_EOL)) . PHP_EOL . self::FOOTER;
     return $content;
 }
Пример #3
0
 /**
  * @param GeneratorPoint $G
  * @param $hash
  * @return int|string
  */
 public function truncateHash(GeneratorPoint $G, $hash)
 {
     $hexSize = strlen($this->adapter->decHex($hash));
     $hashBits = $this->adapter->baseConvert($hash, 10, 2);
     if (strlen($hashBits) < $hexSize * 4) {
         $hashBits = str_pad($hashBits, $hexSize * 4, '0', STR_PAD_LEFT);
     }
     $messageHash = $this->adapter->baseConvert(substr($hashBits, 0, NumberSize::bnNumBits($this->adapter, $G->getOrder())), 2, 10);
     return $messageHash;
 }
Пример #4
0
 /**
  * @param MathAdapterInterface $math
  * @param NamedCurveFp $curve
  * @param GeneratorPoint $generatorPoint
  * @param Hasher $hasher - must be a known hash algorithm
  */
 public function __construct(MathAdapterInterface $math, NamedCurveFp $curve, GeneratorPoint $generatorPoint, Hasher $hasher)
 {
     if (!$curve->contains($generatorPoint->getX(), $generatorPoint->getY())) {
         throw new \RuntimeException('Provided generator point does not exist on curve');
     }
     $this->hasher = $hasher;
     $this->curve = $curve;
     $this->generator = $generatorPoint;
     $this->math = $math;
 }
Пример #5
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.");
     }
 }
 public function testCurve()
 {
     $math = EccFactory::getAdapter();
     $G = CurveFactory::getGeneratorByName("nist-p224");
     $algo = 'sha256';
     // Initialize private key and message hash (decimal)
     $privateKey = $G->getPrivateKeyFrom($this->math->hexDec('F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1'));
     $messageHash = $this->math->hexDec(hash($algo, "sample"));
     // Derive K
     $drbg = RandomGeneratorFactory::getHmacRandomGenerator($privateKey, $messageHash, $algo);
     $k = $drbg->generate($this->G->getOrder());
     //$this->assertEquals($this->math->hexdec($test->expectedK), $k);
     $signer = new Signer($this->math);
     $sig = $signer->sign($privateKey, $messageHash, $k);
     // R and S should be correct
     //$sR = $this->math->hexDec(substr(strtolower($test->expectedRS), 0, 64));
     //$sS = $this->math->hexDec(substr(strtolower($test->expectedRS), 64, 64));
     //$this->assertSame($sR, $sig->getR());
     //$this->assertSame($sS, $sig->getS());
 }
Пример #7
0
 /**
  * {@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;
 }
Пример #8
0
 /**
  * @dataProvider getHmacTestSet
  * @param GeneratorPoint $G
  * @param integer $size
  * @param string $privKey
  * @param string $algo
  * @param string $message
  * @param string $eK expected K hex
  * @param string $eR expected R hex
  * @param string $eS expected S hex
  */
 public function testHmacSignatures(GeneratorPoint $G, $size, $privKey, $algo, $message, $eK, $eR, $eS)
 {
     //echo "Try {$test->curve} / {$test->algorithm} / '{$test->message}'\n";
     $math = $G->getAdapter();
     // Initialize private key and message hash (decimal)
     $privateKey = $G->getPrivateKeyFrom($math->hexDec($privKey));
     $hashHex = hash($algo, $message);
     $messageHash = $math->hexDec($hashHex);
     // Derive K
     $drbg = RandomGeneratorFactory::getHmacRandomGenerator($privateKey, $messageHash, $algo);
     $k = $drbg->generate($G->getOrder());
     $this->assertEquals($k, $math->hexdec($eK), 'k');
     $hexSize = strlen($hashHex);
     $hashBits = $math->baseConvert($messageHash, 10, 2);
     if (strlen($hashBits) < $hexSize * 4) {
         $hashBits = str_pad($hashBits, $hexSize * 4, '0', STR_PAD_LEFT);
     }
     $messageHash = $math->baseConvert(substr($hashBits, 0, NumberSize::bnNumBits($math, $G->getOrder())), 2, 10);
     $signer = new Signer($math);
     $sig = $signer->sign($privateKey, $messageHash, $k);
     // Should be consistent
     $this->assertTrue($signer->verify($privateKey->getPublicKey(), $sig, $messageHash));
     // R and S should be correct
     $sR = $math->hexDec($eR);
     $sS = $math->hexDec($eS);
     $this->assertSame($sR, $sig->getR(), "r {$sR} == " . $sig->getR());
     $this->assertSame($sS, $sig->getS(), "s {$sR} == " . $sig->getS());
 }
Пример #9
0
 /**
  * {@inheritDoc}
  * @see \Mdanter\Ecc\Crypto\Key\PrivateKeyInterface::getCurve()
  */
 public function getCurve()
 {
     return $this->generator->getCurve();
 }
Пример #10
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());
 }
Пример #11
0
 public function parseKey(GeneratorPoint $generator, $data)
 {
     $point = $this->pointSerializer->unserialize($generator->getCurve(), $data);
     return new PublicKey($this->adapter, $generator, $point);
 }
Пример #12
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;
 }