public static function test_signature_validity($Msg, $Qx, $Qy, $R, $S, $expected, $verbose = false) { $p192 = NISTcurve::generator_192(); $curve_192 = NISTcurve::curve_192(); $pubk = new PublicKey($p192, new Point($curve_192, $Qx, $Qy)); $got = $pubk->verifies(PrivateKey::digest_integer($Msg), new Signature($R, $S)); if (bccomp($got, $expected) == 0) { if ($verbose) { print "Signature tested as expected: received " . var_export($got, true) . ", expected " . var_export($expected, true) . ".<br />"; } flush(); } else { print "*** Signature test failed: received " . var_export($got, true) . ", expected " . var_export($expected, true) . ".<br />"; } flush(); }
function recoverPubKey($r, $s, $e, $recoveryFlags, $G) { $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 static $p_over_four; // XXX just assuming only one curve/prime will be used if (!$p_over_four) { $p_over_four = gmp_div(gmp_add($curve->getPrime(), 1), 4); } // 1.1 Compute x if (!$isSecondKey) { $x = $r; } else { $x = gmp_add($r, $G->getOrder()); } // 1.3 Convert x to point $alpha = gmp_mod(gmp_add(gmp_add(gmp_pow($x, 3), gmp_mul($curve->getA(), $x)), $curve->getB()), $curve->getPrime()); $beta = NumberTheory::modular_exp($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 (isBignumEven($beta) == $isYEven) { $y = gmp_sub($curve->getPrime(), $beta); } else { $y = $beta; } // 1.4 Check that nR is at infinity (implicitly done in construtor) $R = new Point($curve, $x, $y, $G->getOrder()); $point_negate = function ($p) { return new Point($p->curve, $p->x, gmp_neg($p->y), $p->order); }; // 1.6.1 Compute a candidate public key Q = r^-1 (sR - eG) $rInv = NumberTheory::inverse_mod($r, $G->getOrder()); $eGNeg = $point_negate(Point::mul($e, $G)); $Q = Point::mul($rInv, Point::add(Point::mul($s, $R), $eGNeg)); // 1.6.2 Test Q as a public key $Qk = new PublicKey($G, $Q); if ($Qk->verifies($e, $signature)) { return $Qk; } return false; }
/** * 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) { $signature = self::decode_signature($sig); $test_signature = new \Signature(gmp_init($signature['r'], 16), gmp_init($signature['s'], 16)); $generator = \SECcurve::generator_secp256k1(); $curve = $generator->getCurve(); if (strlen($key) == '66') { $decompress = BitcoinLib::decompress_public_key($key); $public_key_point = $decompress['point']; } else { $x = gmp_strval(gmp_init(substr($key, 2, 64), 16), 10); $y = gmp_strval(gmp_init(substr($key, 66, 64), 16), 10); $public_key_point = new \Point($curve, $x, $y, $generator->getOrder()); } $public_key = new \PublicKey($generator, $public_key_point); $hash = gmp_init($hash, 16); return $public_key->verifies($hash, $test_signature) == TRUE; }
public function validate_signature($sig, $hash, $key) { // Initialize $signature = $this->decode_signature($sig); $test_signature = new Signature(gmp_init($signature['r'], 16), gmp_init($signature['s'], 16)); $generator = SECcurve::generator_secp256k1(); $curve = $generator->getCurve(); // Check key if (strlen($key) == '66') { $client = new BIP32(); $decompress = $client->decompress_public_key($key); $public_key_point = $decompress['point']; } else { $x = gmp_strval(gmp_init(substr($key, 2, 64), 16), 10); $y = gmp_strval(gmp_init(substr($key, 66, 64), 16), 10); $public_key_point = new Point($curve, $x, $y, $generator->getOrder()); } // Get hash $public_key = new PublicKey($generator, $public_key_point); $hash = gmp_init($hash, 16); // Return return $public_key->verifies($hash, $test_signature) === true; }