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); }
public function getErroneousTypeVectors() { $context = TestCase::getContext(); $msg32 = pack("H*", '03acc83ba10066e791d51e8a8eb90ec325feea7251cb8f979996848fff551d13'); $sig = pack("H*", 'fe5fe404f3d8c21e1204a08c38ff3912d43c5a22541d2f1cdc4977cbcad240015a3b6e9040f62cacf016df4fef9412091592e4908e5e3a7bd2a42a4d1be01951'); $s = ''; $recid = 0; $this->assertEquals(1, secp256k1_ecdsa_recoverable_signature_parse_compact($context, $s, $sig, $recid)); $array = array(); $class = new Secp256k1EcdsaRecoverCompactTest(); $resource = openssl_pkey_new(); return array(array($context, $array, $s), array($context, $resource, $s), array($context, $class, $s), array($context, $msg32, $array), array($context, $msg32, $resource), array($context, $msg32, $class)); }
/** * @param string|BufferInterface $data * @return CompactSignature */ public function parse($data) { $math = $this->ecAdapter->getMath(); $buffer = (new Parser($data, $math))->getBuffer(); if ($buffer->getSize() !== 65) { throw new \RuntimeException('Compact Sig must be 65 bytes'); } $byte = $buffer->slice(0, 1)->getInt(); $sig = $buffer->slice(1, 64); $recoveryFlags = $math->sub($byte, 27); if ($math->cmp($recoveryFlags, 7) > 0) { throw new \RuntimeException('Invalid signature type'); } $isCompressed = $math->cmp($math->bitwiseAnd($recoveryFlags, 4), 0) !== 0; $recoveryId = $math->sub($recoveryFlags, $isCompressed ? 4 : 0); $sig_t = ''; /** @var resource $sig_t */ if (!secp256k1_ecdsa_recoverable_signature_parse_compact($this->ecAdapter->getContext(), $sig->getBinary(), $recoveryId, $sig_t)) { throw new \RuntimeException('Unable to parse compact signature'); } return new CompactSignature($this->ecAdapter, $sig_t, $recoveryId, $isCompressed); }