Example #1
0
 /**
  * @param CompactSignature $signature
  * @param Buffer $messageHash
  * @return PublicKey
  * @throws \Exception
  */
 public function recoverCompact(Buffer $messageHash, CompactSignature $signature)
 {
     $math = $this->getMath();
     $G = $this->getGenerator();
     $isYEven = $math->bitwiseAnd($signature->getRecoveryId(), 1) != 0;
     $isSecondKey = $math->bitwiseAnd($signature->getRecoveryId(), 2) != 0;
     $curve = $G->getCurve();
     // 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 = $signature->getR();
     } else {
         $x = $math->add($signature->getR(), $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->isEven($beta) == $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($signature->getR(), $G->getOrder());
     $eGNeg = $point_negate($G->mul($messageHash->getInt()));
     $Q = $R->mul($signature->getS())->add($eGNeg)->mul($rInv);
     // 1.6.2 Test Q as a public key
     $Qk = new PublicKey($this, $Q);
     if ($this->verify($messageHash, $Qk, new Signature($signature->getR(), $signature->getS()))) {
         return $Qk->setCompressed($signature->isCompressed());
     }
     throw new \Exception('Unable to recover public key');
 }
Example #2
0
 /**
  * @param CompactSignature $signature
  * @param Buffer $messageHash
  * @return \BitWasp\Bitcoin\Key\PublicKey
  * @throws \Exception
  */
 public function recoverCompact(Buffer $messageHash, CompactSignature $signature)
 {
     $pubkey = '';
     $ret = \secp256k1_ecdsa_recover_compact($messageHash->getBinary(), $signature->getBuffer()->slice(1)->getBinary(), (int) $signature->getRecoveryId(), (int) $signature->isCompressed(), $pubkey);
     if ($ret === 1) {
         $publicKey = PublicKeyFactory::fromHex(bin2hex($pubkey));
         return $publicKey->setCompressed($signature->isCompressed());
     }
     throw new \Exception('Unable to recover public key from compact signature');
 }
 /**
  * @param CompactSignature $signature
  * @return Buffer
  */
 public function serialize(CompactSignature $signature)
 {
     return $this->getTemplate()->write([$signature->getFlags(), $signature->getR(), $signature->getS()]);
 }