Beispiel #1
0
 /**
  * @param string $content
  * @param Binary $address
  * @param string $signature
  * @return bool
  * @throws \Exception
  */
 public function verify($content, Binary $address, $signature)
 {
     if (!strpos($signature, self::$SIGNATURE_GLUE)) {
         throw new \Exception('Invalid signature.');
     }
     list($r, $s) = explode(self::$SIGNATURE_GLUE, $signature);
     $math = MathAdapterFactory::getAdapter();
     $serializer = new DerPublicKeySerializer($math);
     $inflatedPublicKey = $this->deserialize($address->getData(), $serializer);
     $hash = $this->hash($content);
     $signer = new Signer($math);
     return $signer->verify($inflatedPublicKey, new Signature($r, $s), $hash);
 }
Beispiel #2
0
 /**
  * {@inheritdoc}
  */
 public function doVerify(string $expected, string $payload, Key $key) : bool
 {
     return $this->signer->verify($this->parser->getPublicKey($key), $this->extractSignature($expected), $this->createSigningHash($payload));
 }
 /**
  * @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());
 }
Beispiel #4
0
 /**
  * @dataProvider getAdaptersWithRand
  */
 public function testSignatureValidityWithGeneratedKeys(MathAdapterInterface $math, RandomNumberGeneratorInterface $rng)
 {
     $generator = EccFactory::getNistCurves($math)->generator192();
     $signer = new Signer($math);
     $privateKey = $generator->createPrivateKey();
     $publicKey = $privateKey->getPublicKey();
     $randomK = $rng->generate($privateKey->getPoint()->getOrder());
     $hash = $rng->generate($generator->getOrder());
     $signature = $signer->sign($privateKey, $hash, $randomK);
     $this->assertTrue($signer->verify($publicKey, $signature, $hash), 'Correctly validates valid hash.');
     $this->assertFalse($signer->verify($publicKey, $signature, $math->sub($hash, 1)), 'Correctly rejects tampered hash.');
 }
 /**
  * Check Sig
  *
  * This function will check a provided DER encoded $sig, a digest of
  * the message to be signed - $hash (the output of _create_txin_signature_hash()),
  * and the $key for the signature to be tested against.
  * Returns TRUE if the signature is valid for this $hash and $key,
  * otherwise returns FALSE.
  *
  * @param    string $sig
  * @param    string $hash
  * @param    string $key
  * @return    boolean
  */
 public static function _check_sig($sig, $hash, $key)
 {
     $math = EccFactory::getAdapter();
     $generator = EccFactory::getSecgCurves()->generator256k1();
     $curve = $generator->getCurve();
     $hash = $math->hexDec($hash);
     $signature = self::decode_signature($sig);
     $test_signature = new Signature($math->hexDec($signature['r']), $math->hexDec($signature['s']));
     if (strlen($key) == '66') {
         $decompress = BitcoinLib::decompress_public_key($key);
         $public_key_point = $decompress['point'];
     } else {
         $x = $math->hexDec(substr($key, 2, 64));
         $y = $math->hexDec(substr($key, 66, 64));
         $public_key_point = $curve->getPoint($x, $y);
     }
     $signer = new Signer($math);
     $public_key = new PublicKey($math, $generator, $public_key_point);
     return $signer->verify($public_key, $test_signature, $hash) == true;
 }
 /**
  * Check Sig
  *
  * This function will check a provided DER encoded $sig, a digest of
  * the message to be signed - $hash (the output of _create_txin_signature_hash()),
  * and the $key for the signature to be tested against.
  * Returns TRUE if the signature is valid for this $hash and $key,
  * otherwise returns FALSE.
  *
  * @param    string $sig
  * @param    string $hash
  * @param    string $key
  * @param    bool   $allowHighS
  * @return bool
  */
 public static function _check_sig($sig, $hash, $key, $allowHighS = self::ALLOW_HIGH_S)
 {
     $math = EccFactory::getAdapter();
     $generator = EccFactory::getSecgCurves()->generator256k1();
     $curve = $generator->getCurve();
     $hash = $math->hexDec($hash);
     $decodedSignature = self::decode_signature($sig);
     $signature = new Signature($math->hexDec($decodedSignature['r']), $math->hexDec($decodedSignature['s']));
     if (!$allowHighS) {
         // if S is > half then someone should have fixed it
         if (self::check_signature_is_high_s($signature)) {
             return false;
         }
     }
     if (strlen($key) == '66') {
         $decompress = BitcoinLib::decompress_public_key($key);
         $public_key_point = $decompress['point'];
     } else {
         $x = $math->hexDec(substr($key, 2, 64));
         $y = $math->hexDec(substr($key, 66, 64));
         $public_key_point = $curve->getPoint($x, $y);
     }
     $signer = new Signer($math);
     $public_key = new PublicKey($math, $generator, $public_key_point);
     return $signer->verify($public_key, $signature, $hash) == true;
 }
 /**
  * @dataProvider getDeterministicSign2Data
  */
 public function testDeterministicSign2($curve, $size, $algo, $privKey, $message, $eK, $eR, $eS)
 {
     //echo "Try {$test->curve} / {$test->algorithm} / '{$test->message}'\n";
     $G = CurveFactory::getGeneratorByName($curve);
     // Initialize private key and message hash (decimal)
     $privateKey = $G->getPrivateKeyFrom($this->math->hexDec($privKey));
     $hashHex = hash($algo, $message);
     $messageHash = $this->math->hexDec($hashHex);
     // Derive K
     $drbg = RandomGeneratorFactory::getHmacRandomGenerator($privateKey, $messageHash, $algo);
     $k = $drbg->generate($G->getOrder());
     $this->assertEquals($this->math->hexdec($eK), $k, 'k');
     $hexSize = strlen($hashHex);
     $hashBits = $this->math->baseConvert($messageHash, 10, 2);
     if (strlen($hashBits) < $hexSize * 4) {
         $hashBits = str_pad($hashBits, $hexSize * 4, '0', STR_PAD_LEFT);
     }
     $messageHash = $this->math->baseConvert(substr($hashBits, 0, $size), 2, 10);
     $signer = new Signer($this->math);
     $sig = $signer->sign($privateKey, $messageHash, $k);
     // R and S should be correct
     $sR = $this->math->hexDec($eR);
     $sS = $this->math->hexDec($eS);
     $this->assertTrue($signer->verify($privateKey->getPublicKey(), $sig, $messageHash));
     $this->assertSame($sR, $sig->getR(), 'r');
     $this->assertSame($sS, $sig->getS(), 's');
 }
 /**
  * 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;
 }