public function test() { $privKey = hash('sha256', 'private key', true); $msg32 = hash('sha256', 'msg', true); $pub_t = ''; /** @var resource $pub_t */ $context = TestCase::getContext(); // Create public key of our private key $this->assertEquals(1, secp256k1_ec_pubkey_create($context, $pub_t, $privKey)); // Create recoverable signature $r_sig_t = ''; /** @var resource $r_sig_t */ $this->assertEquals(1, secp256k1_ecdsa_sign_recoverable($context, $r_sig_t, $msg32, $privKey)); $this->assertEquals(SECP256K1_TYPE_RECOVERABLE_SIG, get_resource_type($r_sig_t)); // Recover public key from the signature $r_pubkey_t = ''; /** @var resource $r_pubkey_t */ $this->assertEquals(1, secp256k1_ecdsa_recover($context, $r_pubkey_t, $r_sig_t, $msg32)); // Compare the two public keys $sPubkey = ''; $srPubkey = ''; $this->assertEquals(1, secp256k1_ec_pubkey_serialize($context, $sPubkey, $pub_t, 0)); $this->assertEquals(1, secp256k1_ec_pubkey_serialize($context, $srPubkey, $r_pubkey_t, 0)); $this->assertEquals($sPubkey, $srPubkey); // Double check that serialize(sig) == serialize(parse(serialize(sig)) $sSig = ''; /** @var resource $sSig */ $recid = ''; secp256k1_ecdsa_recoverable_signature_serialize_compact($context, $r_sig_t, $sSig, $recid); $parsedSig = ''; /** @var resource $parsedSig */ $this->assertEquals(1, secp256k1_ecdsa_recoverable_signature_parse_compact($context, $parsedSig, $sSig, $recid)); $sSigAgain = ''; $recidAgain = ''; secp256k1_ecdsa_recoverable_signature_serialize_compact($context, $parsedSig, $sSigAgain, $recidAgain); // Prepare expected DER sig $rl = 32; $r = substr($sSig, 0, 32); if (ord($sSig[0]) > 0x80) { $rl++; $r = "" . $r; } $sl = 32; $s = substr($sSig, 32, 32); if (ord($sSig[32]) > 0x80) { $sl++; $s = "" . $s; } $t = 4 + $rl + $sl; $der = "0" . chr($t) . "" . chr($rl) . $r . "" . chr($sl) . $s; $plain = ''; /** @var resource $plain */ // Test that conversion is successful $this->assertEquals(1, secp256k1_ecdsa_recoverable_signature_convert($context, $plain, $r_sig_t)); // Test the converted sig's DER output matches what we expect $derSer = ''; $this->assertEquals(1, secp256k1_ecdsa_signature_serialize_der($context, $derSer, $plain)); $this->assertEquals($der, $derSer); }
/** * @param CompactSignature $signature * @return BufferInterface */ private function doSerialize(CompactSignature $signature) { $sig_t = ''; $recid = ''; if (!secp256k1_ecdsa_recoverable_signature_serialize_compact($this->ecAdapter->getContext(), $signature->getResource(), $sig_t, $recid)) { throw new \RuntimeException('Secp256k1 serialize compact failure'); } return new Buffer(chr((int) $signature->getFlags()) . $sig_t, 65, $this->ecAdapter->getMath()); }
/** * @param EcAdapter $ecAdapter * @param resource $secp256k1_ecdsa_signature_t * @param int $recid * @param bool $compressed */ public function __construct(EcAdapter $ecAdapter, $secp256k1_ecdsa_signature_t, $recid, $compressed) { $math = $ecAdapter->getMath(); if (!is_bool($compressed)) { throw new \InvalidArgumentException('CompactSignature: compressed must be a boolean'); } if (!is_resource($secp256k1_ecdsa_signature_t) || SECP256K1_TYPE_RECOVERABLE_SIG !== get_resource_type($secp256k1_ecdsa_signature_t)) { throw new \RuntimeException('CompactSignature: must pass recoverable signature resource'); } $ser = ''; $recidout = ''; secp256k1_ecdsa_recoverable_signature_serialize_compact($ecAdapter->getContext(), $secp256k1_ecdsa_signature_t, $ser, $recidout); list($r, $s) = array_map(function ($val) use($math) { return $math->hexDec(bin2hex($val)); }, str_split($ser, 32)); $this->resource = $secp256k1_ecdsa_signature_t; $this->r = $r; $this->s = $s; $this->recid = $recid; $this->compressed = $compressed; $this->ecAdapter = $ecAdapter; }
/** * @param BufferInterface $msg32 * @param PrivateKey $privateKey * @return CompactSignature */ private function doSignCompact(BufferInterface $msg32, PrivateKey $privateKey) { $sig_t = ''; /** @var resource $sig_t */ if (1 !== secp256k1_ecdsa_sign_recoverable($this->context, $msg32->getBinary(), $privateKey->getBinary(), $sig_t)) { throw new \RuntimeException('Secp256k1: failed to sign'); } $recid = ''; $ser = ''; if (!secp256k1_ecdsa_recoverable_signature_serialize_compact($this->context, $sig_t, $ser, $recid)) { throw new \RuntimeException('Failed to obtain recid'); } unset($ser); return new CompactSignature($this, $sig_t, $recid, $privateKey->isCompressed()); }