/** * @param PublicKey $publicKey * @return BufferInterface */ private function doSerialize(PublicKey $publicKey) { $serialized = ''; $isCompressed = $publicKey->isCompressed(); if (!secp256k1_ec_pubkey_serialize($this->ecAdapter->getContext(), $publicKey->getResource(), $isCompressed, $serialized)) { throw new \RuntimeException('Secp256k1: Failed to serialize public key'); } return new Buffer($serialized, $isCompressed ? PublicKey::LENGTH_COMPRESSED : PublicKey::LENGTH_UNCOMPRESSED, $this->ecAdapter->getMath()); }
/** * @param int $tweak * @return PublicKey * @throws \Exception */ public function tweakMul($tweak) { $context = $this->ecAdapter->getContext(); $math = $this->ecAdapter->getMath(); $bin = pack('H*', str_pad($math->decHex($tweak), 64, '0', STR_PAD_LEFT)); $clone = $this->clonePubkey(); if (1 !== secp256k1_ec_pubkey_tweak_mul($context, $clone, $bin)) { throw new \RuntimeException('Secp256k1: tweak mul failed.'); } return new PublicKey($this->ecAdapter, $clone, $this->compressed); }
/** * @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); }
/** * @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 \BitWasp\Buffertools\BufferInterface|string $data * @return PrivateKey */ public function parse($data) { return $this->fromParser(new Parser($data, $this->ecAdapter->getMath())); }
/** * @param NetworkInterface $network * @return string */ public function toWif(NetworkInterface $network = null) { $network = $network ?: Bitcoin::getNetwork(); $wifSerializer = new WifPrivateKeySerializer($this->ecAdapter->getMath(), new PrivateKeySerializer($this->ecAdapter)); return $wifSerializer->serialize($network, $this); }