public function verifies($hash, Signature $signature) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { $G = $this->generator; $n = $this->generator->getOrder(); $point = $this->point; $r = $signature->getR(); $s = $signature->getS(); if (gmp_cmp($r, 1) < 0 || gmp_cmp($r, gmp_sub($n, 1)) > 0) { return false; } if (gmp_cmp($s, 1) < 0 || gmp_cmp($s, gmp_sub($n, 1)) > 0) { return false; } $c = NumberTheory::inverse_mod($s, $n); $u1 = gmp_Utils::gmp_mod2(gmp_mul($hash, $c), $n); $u2 = gmp_Utils::gmp_mod2(gmp_mul($r, $c), $n); $xy = Point::add(Point::mul($u1, $G), Point::mul($u2, $point)); $v = gmp_Utils::gmp_mod2($xy->getX(), $n); if (gmp_cmp($v, $r) == 0) { return true; } else { return false; } } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { $G = $this->generator; $n = $this->generator->getOrder(); $point = $this->point; $r = $signature->getR(); $s = $signature->getS(); if (bccomp($r, 1) == -1 || bccomp($r, bcsub($n, 1)) == 1) { return false; } if (bccomp($s, 1) == -1 || bccomp($s, bcsub($n, 1)) == 1) { return false; } $c = NumberTheory::inverse_mod($s, $n); $u1 = bcmod(bcmul($hash, $c), $n); $u2 = bcmod(bcmul($r, $c), $n); $xy = Point::add(Point::mul($u1, $G), Point::mul($u2, $point)); $v = bcmod($xy->getX(), $n); if (bccomp($v, $r) == 0) { return true; } else { return false; } } else { throw new ErrorException("Please install BCMATH or GMP"); } } }
public function GOST_verifies($hash, Signature $signature) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { $G = $this->generator; //P $n = $this->generator->getOrder(); //q $point = $this->point; //Q $r = $signature->getR(); $s = $signature->getS(); if (gmp_cmp($r, 1) < 0 || gmp_cmp($r, gmp_sub($n, 1)) > 0) { return false; } if (gmp_cmp($s, 1) < 0 || gmp_cmp($s, gmp_sub($n, 1)) > 0) { return false; } //step 3 GOST $e = gmp_Utils::gmp_mod2($hash, $n); if (gmp_cmp($e, '0') === 0) { $e = gmp_init('1'); } // step 4 GOST $v = gmp_strval(gmp_invert($e, $n)); // step 5 GOST $z1 = gmp_Utils::gmp_mod2(gmp_mul($s, $v), $n); $z2 = gmp_Utils::gmp_mod2(gmp_mul(gmp_neg($r), $v), $n); // step 6 GOST $C = Point::add(Point::mul($z1, $G), Point::mul($z2, $point)); $R = gmp_Utils::gmp_mod2($C->getX(), $n); if (0) { echo "n - " . $n . "\n"; echo "h - " . $hash . "\n"; echo "e - " . gmp_Utils::gmp_dechex($e) . "\n"; echo "v - " . gmp_Utils::gmp_dechex($v) . "\n"; echo "r - " . $r . "\n"; echo "s - " . $s . "\n"; echo "z1 - " . gmp_Utils::gmp_dechex($z1) . "\nz2 - " . gmp_Utils::gmp_dechex($z2) . "\n"; echo "Q - " . $point . "\nG - " . $G . "\n"; echo "C - " . $C . "\nR - " . $R . "\n"; } if (gmp_cmp($R, $r) == 0) { return true; } else { return false; } } else { throw new ErrorException("Please install GMP"); } }
/** * 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) { // Pad r and s to 64 characters. $rh = str_pad(BitcoinLib::hex_encode($signature->getR()), 64, '0', STR_PAD_LEFT); $sh = str_pad(BitcoinLib::hex_encode($signature->getS()), 64, '0', STR_PAD_LEFT); // Check if the first byte of each has its highest bit set, $t1 = unpack("H*", pack('H*', substr($rh, 0, 2)) & pack('H*', '80')); $t2 = unpack("H*", pack('H*', substr($sh, 0, 2)) & pack('H*', '80')); // if so, the result != 00, and must be padded. $r = $t1[1] !== '00' ? '00' . $rh : $rh; $s = $t2[1] !== '00' ? '00' . $sh : $sh; // Create the signature. $der_sig = '30' . self::_dec_to_bytes(4 + (strlen($r) + strlen($s)) / 2, 1) . '02' . self::_dec_to_bytes(strlen($r) / 2, 1) . $r . '02' . self::_dec_to_bytes(strlen($s) / 2, 1) . $s . '01'; return $der_sig; }