public function testSerialize() { $hex = '41414141'; $dec = EccFactory::getAdapter()->hexDec($hex); $bin = pack("H*", $hex); $this->buffer = Buffer::hex($hex); // Check Binary $retBinary = $this->buffer->getBinary(); $this->assertSame($bin, $retBinary); // Check Hex $this->assertSame($hex, $this->buffer->getHex()); // Check Decimal $this->assertSame($dec, $this->buffer->getInt()); }
public function testGetBufferEmptyNull() { $buffer = new Buffer(); $this->parser = new Parser($buffer); $parserData = $this->parser->getBuffer()->getBinary(); $bufferData = $buffer->getBinary(); $this->assertSame($parserData, $bufferData); }
/** * @param Buffer $bits * @return array */ public function unpackCompact(Buffer $bits) { $bitStr = $bits->getBinary(); // Unpack and decode $sci = array_map(function ($value) { return $this->hexDec($value); }, unpack('H2exp/H6mul', $bitStr)); return $sci; }
/** * Encode a given hex string in base58 * * @param Buffer $binary * @return string * @throws \Exception */ public static function encode(Buffer $binary) { $size = $binary->getSize(); if ($binary->getBinary() === '') { return ''; } $math = Bitcoin::getMath(); $orig = $binary->getBinary(); $decimal = $binary->getInt(); $return = ''; while ($math->cmp($decimal, 0) > 0) { list($decimal, $rem) = $math->divQr($decimal, 58); $return .= self::$base58chars[$rem]; } $return = strrev($return); //leading zeros for ($i = 0; $i < $size && $orig[$i] === ""; $i++) { $return = '1' . $return; } return $return; }
/** * @param \BitWasp\Buffertools\Buffer $sig * @return bool * @throws SignatureNotCanonical */ public static function isDERSignature(Buffer $sig) { $checkVal = function ($fieldName, $start, $length, $binaryString) { if ($length == 0) { throw new SignatureNotCanonical('Signature ' . $fieldName . ' length is zero'); } $typePrefix = ord(substr($binaryString, $start - 2, 1)); if ($typePrefix !== 0x2) { throw new SignatureNotCanonical('Signature ' . $fieldName . ' value type mismatch'); } $val = substr($binaryString, $start, $length); $vAnd = $val[0] & pack("H*", '80'); if (ord($vAnd) === 128) { throw new SignatureNotCanonical('Signature ' . $fieldName . ' value is negative'); } if ($length > 1 && ord($val[0]) == 0x0 && !ord($val[1] & pack('H*', '80'))) { throw new SignatureNotCanonical('Signature ' . $fieldName . ' value excessively padded'); } }; $bin = $sig->getBinary(); $size = $sig->getSize(); if ($size < 9) { throw new SignatureNotCanonical('Signature too short'); } if ($size > 73) { throw new SignatureNotCanonical('Signature too long'); } if (ord($bin[0]) !== 0x30) { throw new SignatureNotCanonical('Signature has wrong type'); } if (ord($bin[1]) !== $size - 3) { throw new SignatureNotCanonical('Signature has wrong length marker'); } $lenR = ord($bin[3]); $startR = 4; if (5 + $lenR >= $size) { throw new SignatureNotCanonical('Signature S length misplaced'); } $lenS = ord($bin[5 + $lenR]); $startS = 4 + $lenR + 2; if ($lenR + $lenS + 7 !== $size) { throw new SignatureNotCanonical('Signature R+S length mismatch'); } $checkVal('R', $startR, $lenR, $bin); $checkVal('S', $startS, $lenS, $bin); return true; }
/** * @param Buffer $vch * @param bool $fRequireMinimal * @param int $maxNumSize * @param Math|null $math * @return self */ public static function buffer(Buffer $vch, $fRequireMinimal, $maxNumSize = self::MAX_NUM_SIZE, Math $math = null) { $size = $vch->getSize(); if ($size > $maxNumSize) { throw new \RuntimeException('Script number overflow'); } if ($fRequireMinimal && $size > 0) { $binary = $vch->getBinary(); if (ord($binary[$size - 1]) & 0x7f === 0) { if ($size <= 1 || ord($binary[$size - 2]) & 0x80 === 0) { throw new \RuntimeException('Non-minimally encoded script number'); } } } $math = $math ?: Bitcoin::getMath(); $number = new self(0, $math); $number->number = $number->parseBuffer($vch); return $number; }
/** * @param Buffer $publicKey * @return bool */ public static function isCompressedOrUncompressed(Buffer $publicKey) { $vchPubKey = $publicKey->getBinary(); if ($publicKey->getSize() < 33) { return false; } if (ord($vchPubKey[0]) === 0x4) { if ($publicKey->getSize() !== 65) { // Invalid length for uncompressed key return false; } } elseif (in_array($vchPubKey[0], array(hex2bin(self::KEY_COMPRESSED_EVEN), hex2bin(self::KEY_COMPRESSED_ODD)))) { if ($publicKey->getSize() !== 33) { return false; } } else { return false; } return true; }
/** * Push data into the stack. * * @param $data * @return $this * @throws \Exception */ public function push(Buffer $data) { $length = $data->getSize(); $parsed = new Parser('', $this->math); /** Note that larger integers are serialized without flipping bits - Big endian */ if ($length < $this->opcodes->getOpByName('OP_PUSHDATA1')) { $varInt = Buffertools::numToVarInt($length); $data = new Buffer($varInt->getBinary() . $data->getBinary(), null, $this->math); $parsed->writeBytes($data->getSize(), $data); } else { if ($length <= 0xff) { $lengthSize = 1; } elseif ($length <= 0xffff) { $lengthSize = 2; } else { $lengthSize = 4; } $op = $this->opcodes->getOpByName('OP_PUSHDATA' . $lengthSize); $parsed->writeBytes(1, Buffer::int($op))->writeBytes($lengthSize, Buffer::int($length), true)->writeBytes($length, $data); } $this->script .= $parsed->getBuffer()->getBinary(); return $this; }
/** * Write $data as $bytes bytes. Can be flipped if needed. * * @param integer $bytes * @param $data * @param bool $flipBytes * @return $this */ public function writeBytes($bytes, $data, $flipBytes = false) { // Treat $data to ensure it's a buffer, with the correct size if ($data instanceof SerializableInterface) { $data = $data->getBuffer(); } if ($data instanceof Buffer) { // only create a new buffer if the size does not match if ($data->getSize() != $bytes) { $data = new Buffer($data->getBinary(), $bytes, $this->math); } } else { // Convert to a buffer $data = Buffer::hex($data, $bytes, $this->math); } // At this point $data will be a Buffer $binary = $data->getBinary(); if ($flipBytes) { $binary = Buffertools::flipBytes($binary); } $this->string .= $binary; return $this; }
/** * @param Buffer $msg32 * @param PrivateKey $privateKey * @return CompactSignature */ private function doSignCompact(Buffer $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()); }
/** * @param PublicKeyInterface $publicKey * @return bool */ public function checkInvolvesKey(PublicKeyInterface $publicKey) { return $publicKey->getPubKeyHash()->getBinary() === $this->hash->getBinary(); }
/** * Do HMAC hashing on $data and $salt * * @param string $algo * @param Buffer $data * @param Buffer $salt * @return Buffer */ public static function hmac($algo, Buffer $data, Buffer $salt) { return new Buffer(hash_hmac($algo, $data->getBinary(), $salt->getBinary(), true)); }
/** * @param Buffer $hash * @return bool */ public function containsHash(Buffer $hash) { return array_key_exists($hash->getBinary(), $this->heightByHash); }
<?php require "../vendor/autoload.php"; use BitWasp\Buffertools\Buffer; use BitWasp\Buffertools\BufferHex; use BitWasp\Buffertools\BufferInt; // Binary data and ASCII can be passed directly to a Buffer $binary = new Buffer('hello world'); echo $binary->getBinary() . PHP_EOL; echo $binary->getHex() . PHP_EOL; // BufferHex and BufferInt convert data to binary $hex = new BufferHex('68656c6c6f20776f726c64'); echo $binary->getBinary() . PHP_EOL; echo $hex->getHex() . PHP_EOL; // All Buffers expose getBinary(), getInt(), getHex() $int = new BufferInt(65); echo $int->getBinary() . PHP_EOL; echo $int->getInt() . PHP_EOL; echo $int->getHex() . PHP_EOL;
/** * @param $opCode * @param Buffer $pushData * @return bool * @throws \Exception */ public function checkMinimalPush($opCode, Buffer $pushData) { $pushSize = $pushData->getSize(); $binary = $pushData->getBinary(); $opcodes = $this->script->getOpCodes(); if ($pushSize == 0) { return $opcodes->isOp($opCode, 'OP_0'); } elseif ($pushSize == 1 && ord($binary[0]) >= 1 && ord($binary[0]) <= 16) { return $opCode == $opcodes->getOpByName('OP_1') + (ord($binary[0]) - 1); } elseif ($pushSize == 1 && ord($binary[0]) == 0x81) { return $opcodes->isOp($opCode, 'OP_1NEGATE'); } elseif ($pushSize <= 75) { return $opCode == $pushSize; } elseif ($pushSize <= 255) { return $opcodes->isOp($opCode, 'OP_PUSHDATA1'); } elseif ($pushSize <= 65535) { return $opcodes->isOp($opCode, 'OP_PUSHDATA2'); } return true; }
/** * @param $opCode * @param Buffer $pushData * @return bool * @throws \Exception */ public function checkMinimalPush($opCode, Buffer $pushData) { $pushSize = $pushData->getSize(); $binary = $pushData->getBinary(); if ($pushSize === 0) { return $opCode === Opcodes::OP_0; } elseif ($pushSize === 1) { $first = ord($binary[0]); if ($first >= 1 && $first <= 16) { return $opCode === Opcodes::OP_1 + ($first - 1); } elseif ($first === 0x81) { return $opCode === Opcodes::OP_1NEGATE; } } elseif ($pushSize <= 75) { return $opCode === $pushSize; } elseif ($pushSize <= 255) { return $opCode === Opcodes::OP_PUSHDATA1; } elseif ($pushSize <= 65535) { return $opCode === Opcodes::OP_PUSHDATA2; } return true; }
/** * Initialize container * * @param Buffer $script */ public function __construct(Buffer $script = null) { $this->script = $script instanceof Buffer ? $script->getBinary() : ''; $this->opcodes = new Opcodes(); }
/** * @param Buffer $publicKey * @return bool */ public function validatePublicKey(Buffer $publicKey) { $ret = (bool) \secp256k1_ec_pubkey_verify($publicKey->getBinary()); return $ret; }