/** * Creates a binary signature with R and S coordinates * * @param Signature $signature * * @return string */ private function createSignatureHash(Signature $signature) : string { $length = $this->getSignatureLength(); return pack('H*', sprintf('%s%s', str_pad($this->adapter->decHex($signature->getR()), $length, '0', STR_PAD_LEFT), str_pad($this->adapter->decHex($signature->getS()), $length, '0', STR_PAD_LEFT))); }
/** * Encode Signature * * This function accepts a signature object, and information about * the txout being spent, and the relevant key for signing, and * encodes the signature in DER format. * * @param Signature $signature * @return string */ public static function encode_signature(Signature $signature) { $math = EccFactory::getAdapter(); $generator = EccFactory::getSecgCurves($math)->generator256k1(); // if S is > half then we substract from N if (self::check_signature_is_high_s($signature)) { $n = $generator->getOrder(); $signature = new Signature($signature->getR(), $math->sub($n, $signature->getS())); } $rBin = pack("H*", BitcoinLib::hex_encode($signature->getR())); $sBin = pack("H*", BitcoinLib::hex_encode($signature->getS())); // Pad R and S if their highest bit is flipped, ie, // they are negative. $rt = $rBin[0] & pack('H*', '80'); if (ord($rt) == 128) { $rBin = pack('H*', '00') . $rBin; } $st = $sBin[0] & pack('H*', '80'); if (ord($st) == 128) { $sBin = pack('H*', '00') . $sBin; } $r = bin2hex($rBin); $s = bin2hex($sBin); // Create the signature. $der_sig = '30' . self::_dec_to_bytes(4 + (strlen($r) + strlen($s)) / 2, 1) . '02' . self::pushdata($r) . '02' . self::pushdata($s) . '01'; return $der_sig; }
/** * Encode Signature * * This function accepts a signature object, and information about * the txout being spent, and the relevant key for signing, and * encodes the signature in DER format. * * @param Signature $signature * @return string */ public static function encode_signature(Signature $signature) { $rBin = pack("H*", BitcoinLib::hex_encode($signature->getR())); $sBin = pack("H*", BitcoinLib::hex_encode($signature->getS())); // Pad R and S if their highest bit is flipped, ie, // they are negative. $rt = $rBin[0] & pack('H*', '80'); if (ord($rt) == 128) { $rBin = pack('H*', '00') . $rBin; } $st = $sBin[0] & pack('H*', '80'); if (ord($st) == 128) { $sBin = pack('H*', '00') . $sBin; } $r = bin2hex($rBin); $s = bin2hex($sBin); // Create the signature. $der_sig = '30' . self::_dec_to_bytes(4 + (strlen($r) + strlen($s)) / 2, 1) . '02' . self::pushdata($r) . '02' . self::pushdata($s) . '01'; return $der_sig; }
/** * encode a message signature * * @param Signature $signature * @param $i * @param bool $compressed * @return string * @throws \Exception */ private static function encodeMessageSignature(Signature $signature, $i, $compressed = false) { if (!$compressed) { throw new \Exception("Uncompressed message signing not supported!"); } $val = $i + 27; if ($compressed) { $val += 4; } return hex2bin(implode("", [BitcoinLib::hex_encode($val), str_pad(BitcoinLib::hex_encode($signature->getR()), 64, '0', STR_PAD_LEFT), str_pad(BitcoinLib::hex_encode($signature->getS()), 64, '0', STR_PAD_LEFT)])); }