function token_verify($Hash, $Qx, $Qy, $R, $S) { $pGOST = GOSTcurve::generator_GOST(); $curve_GOST = GOSTcurve::curve_GOST(); $pubk = new PublicKey($pGOST, new Point($curve_GOST, gmp_Utils::gmp_hexdec('0x' . $Qx), gmp_Utils::gmp_hexdec('0x' . $Qy))); $got = $pubk->GOST_verifies(gmp_Utils::gmp_hexdec('0x' . $Hash), new Signature(gmp_Utils::gmp_hexdec('0x' . $R), gmp_Utils::gmp_hexdec('0x' . $S))); return $got; }
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 contains($x, $y) { $eq_zero = null; if (extension_loaded('gmp') && USE_EXT == 'GMP') { $eq_zero = gmp_cmp(gmp_Utils::gmp_mod2(gmp_sub(gmp_pow($y, 2), gmp_add(gmp_add(gmp_pow($x, 3), gmp_mul($this->a, $x)), $this->b)), $this->prime), 0); if ($eq_zero == 0) { return true; } else { return false; } } else { throw new ErrorException("Please install GMP"); } }
public static function generator_GOST() { # GOST Curve: if (extension_loaded('gmp') && USE_EXT == 'GMP') { $_Gx = '1'; $_Gy = gmp_Utils::gmp_hexdec('0x8d91e471e0989cda27df505a453f2b7635294f2ddf23e3b122acc99c9e9f1e14'); $_r = gmp_Utils::gmp_hexdec('0xffffffffffffffffffffffffffffffff6c611070995ad10045841b09b761b893'); $curve_GOST = self::curve_GOST(); $generator_GOST = new Point($curve_GOST, $_Gx, $_Gy, $_r); } else { return false; } return $generator_GOST; }
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"); } }
public function getPublicPoint() { if (extension_loaded('gmp') && USE_EXT == 'GMP') { //alice selects a random number between 1 and the order of the generator point(private) $n = $this->generator->getOrder(); $this->secret = gmp_Utils::gmp_random($n); //Alice computes da * generator Qa is public, da is private $this->pubPoint = Point::mul($this->secret, $this->generator); return $this->pubPoint; } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { //alice selects a random number between 1 and the order of the generator point(private) $n = $this->generator->getOrder(); $this->secret = bcmath_Utils::bcrand($n); //Alice computes da * generator Qa is public, da is private $this->pubPoint = Point::mul($this->secret, $this->generator); return $this->pubPoint; } else { throw new ErrorException("Please Install BCMATH or GMP."); } } }
public static function int_to_string($x) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { if (gmp_cmp($x, 0) >= 0) { if (gmp_cmp($x, 0) == 0) { return chr(0); } $result = ""; while (gmp_cmp($x, 0) > 0) { $q = gmp_div($x, 256, 0); $r = gmp_Utils::gmp_mod2($x, 256); $ascii = chr($r); $result = $ascii . $result; $x = $q; } return $result; } } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { if (bccomp($x, 0) != -1) { if (bccomp($x, 0) == 0) { return chr(0); } $result = ""; while (bccomp($x, 0) == 1) { $q = bcdiv($x, 256, 0); $r = bcmod($x, 256); $ascii = chr($r); $result = $ascii . $result; $x = $q; } return $result; } } else { throw new ErrorException("Please install BCMATH or GMP"); } } }
public static function order_mod($x, $m) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { if ($m <= 1) { return 0; } if (gcd($x, m) == 1) { $z = $x; $result = 1; while ($z != 1) { $z = gmp_strval(gmp_Utils::gmp_mod2(gmp_mul($z, $x), $m)); $result = gmp_add($result, 1); } return gmp_strval($result); } } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { if ($m <= 1) { return 0; } if (gcd($x, m) == 1) { $z = $x; $result = 1; while ($z != 1) { $z = bcmod(bcmul($z, $x), $m); $result = bcadd($result, 1); } return $result; } } else { throw new ErrorException("Please install BCMATH or GMP"); } } }
public static function generator_521() { # NIST Curve P-521: if (extension_loaded('gmp') && USE_EXT == 'GMP') { $_p = '6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151'; $_r = '6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449'; $_b = gmp_Utils::gmp_hexdec('0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'); $_Gx = gmp_Utils::gmp_hexdec('0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'); $_Gy = gmp_Utils::gmp_hexdec('0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'); $curve_521 = new CurveFp($_p, -3, $_b); $generator_521 = new Point($curve_521, $_Gx, $_Gy, $_r); } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { $_p = '6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151'; $_r = '6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449'; $_b = bcmath_Utils::bchexdec('0x051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00'); $_Gx = bcmath_Utils::bchexdec('0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66'); $_Gy = bcmath_Utils::bchexdec('0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650'); $curve_521 = new CurveFp($_p, -3, $_b); $generator_521 = new Point($curve_521, $_Gx, $_Gy, $_r); } } return $generator_521; }
/** * Generate a new private key * * @author Jacob Bruce * @return string * @access public */ public static function getNewPrivKey() { $g = SECcurve::generator_secp256k1(); $n = $g->getOrder(); do { if (extension_loaded('gmp') && USE_EXT == 'GMP') { $privKey = gmp_Utils::gmp_random($n); } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { $privKey = bcmath_Utils::bcrand(1, $n); } } $privKeyHex = self::encodeHex($privKey); } while ($privKey < 1 || strlen($privKeyHex) > 64); return str_pad($privKeyHex, 64, '0', STR_PAD_LEFT); }
public static function test_multiply(CurveFp $c, $x1, $y1, $m, $x3, $y3, $verbose = false) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { // expect that on curve c, m * (x2, y2) = (x3, y3) $p1 = new Point($c, $x1, $y1); $p3 = Point::mul($m, $p1); if ($verbose) { echo $p1 . " * " . $m . " = " . $p3; } if ($p3 instanceof Point) { if (gmp_Utils::gmp_mod2($p3->getX(), 23) != $x3 || gmp_Utils::gmp_mod2($p3->getY(), 23) != $y3) { echo " MULT TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " MULT TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } else { if ($p3 == 'infinity') { echo " INFINITY MULT TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " INFINITY MULT TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { // expect that on curve c, m * (x2, y2) = (x3, y3) $p1 = new Point($c, $x1, $y1); $p3 = Point::mul($m, $p1); if ($verbose) { echo $p1 . " * " . $m . " = " . $p3; } flush(); if ($p3 instanceof Point) { if (bcmod($p3->getX(), 23) != $x3 || bcmod($p3->getY(), 23) != $y3) { echo " MULT TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " MULT TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } else { if ($p3 == 'infinity') { echo " INFINITY MULT TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " INFINITY MULT TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } } } }
/** * Decompress Public Key * * Accepts a y_byte, 02 or 03 indicating whether the Y coordinate is * odd or even, and $passpoint, which is simply a hexadecimal X coordinate. * Using this data, it is possible to deconstruct the original * uncompressed public key. * * @param $key * @return array|bool */ public static function decompress_public_key($key) { $y_byte = substr($key, 0, 2); $x_coordinate = substr($key, 2); $x = gmp_strval(gmp_init($x_coordinate, 16), 10); $curve = \SECcurve::curve_secp256k1(); $generator = \SECcurve::generator_secp256k1(); try { $x3 = \NumberTheory::modular_exp($x, 3, $curve->getPrime()); $y2 = gmp_add($x3, $curve->getB()); $y0 = \NumberTheory::square_root_mod_prime(gmp_strval($y2, 10), $curve->getPrime()); if ($y0 == FALSE) { return FALSE; } $y1 = gmp_strval(gmp_sub($curve->getPrime(), $y0), 10); $y_coordinate = $y_byte == '02' ? \gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) == '0' ? $y0 : $y1 : (\gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) !== '0' ? $y0 : $y1); $y_coordinate = str_pad(gmp_strval($y_coordinate, 16), 64, '0', STR_PAD_LEFT); $point = new \Point($curve, gmp_strval(gmp_init($x_coordinate, 16), 10), gmp_strval(gmp_init($y_coordinate, 16), 10), $generator->getOrder()); } catch (\Exception $e) { return FALSE; } return array('x' => $x_coordinate, 'y' => $y_coordinate, 'point' => $point, 'public_key' => '04' . $x_coordinate . $y_coordinate); }
/** * CKD * * This recursive function accepts $master, a parent extended key, * and an array of address bytes (the $address_definition tuple). It * pop's the next value from the $address_definition tuple and * generates the desired key. If the $address_definition tuple is * empty, then it returns the key. If not, then it calls itself again * with the new key and the tuple with the remaining key indexes to * generate, but will terminate with an array containing the desired * key at index 0, and it's human readable definition in the second. * * @param string $master * @param array $address_definition * @return array */ public static function CKD($master, $address_definition, $generated = array()) { $previous = self::import($master); if ($previous['type'] == 'private') { $private_key = $previous['key']; $public_key = BitcoinLib::private_key_to_public_key($private_key, TRUE); } else { if ($previous['type'] == 'public') { $public_key = $previous['key']; } else { // Exception here? return FALSE; } } $fingerprint = substr(hash('ripemd160', hash('sha256', pack("H*", $public_key), TRUE)), 0, 8); $i = array_pop($address_definition); $is_prime = self::check_is_prime_hex($i); if ($is_prime == 1) { if ($previous['type'] == 'public') { return FALSE; } // Cannot derive private from public key - Exception here? $data = '00' . $private_key . $i; } else { if ($is_prime == 0) { $data = $public_key . $i; } } if (!isset($data)) { return FALSE; } $I = hash_hmac('sha512', pack("H*", $data), pack("H*", $previous['chain_code'])); $I_l = substr($I, 0, 64); $I_r = substr($I, 64, 64); if (self::check_valid_hmac_key($I_l) == FALSE) { // Check the key is in a valid range. // calculate the next i in the sequence, and start over with that. $new_i = self::calc_address_bytes(self::get_address_number($i) + 1, $is_prime); array_push($address_definition, $new_i); return self::CKD($master, $address_definition, $generated); } // Keep a record of the address being built. Done after error // checking so only valid keys get to this point. if (count($generated) == 0 && $previous['depth'] == 0) { array_push($generated, $previous['type'] == 'private' ? 'm' : 'M'); } array_push($generated, self::get_address_number($i, $is_prime) . ($is_prime == 1 ? "'" : NULL)); $g = \SECcurve::generator_secp256k1(); $n = $g->getOrder(); if ($previous['type'] == 'private') { // (Il + kpar) mod n $key = str_pad(gmp_strval(\gmp_Utils::gmp_mod2(gmp_add(gmp_init($I_l, 16), gmp_init($private_key, 16)), $n), 16), 64, '0', STR_PAD_LEFT); } else { if ($previous['type'] == 'public') { // newPoint + parentPubkeyPoint $decompressed = BitcoinLib::decompress_public_key($public_key); // Can return FALSE. Throw exception? $curve = \SECcurve::curve_secp256k1(); // Prepare offset, by multiplying Il by g, and adding this to the previous public key point. // Create a new point by adding the two. $new_point = \Point::add(\Point::mul(gmp_init($I_l, 16), $g), $decompressed['point']); $new_x = str_pad(gmp_strval($new_point->getX(), 16), 64, '0', STR_PAD_LEFT); $new_y = str_pad(gmp_strval($new_point->getY(), 16), 64, '0', STR_PAD_LEFT); $key = BitcoinLib::compress_public_key('04' . $new_x . $new_y); } } if (!isset($key)) { return FALSE; } $data = array('network' => $previous['network'], 'testnet' => $previous['testnet'], 'magic_bytes' => $previous['magic_bytes'], 'type' => $previous['type'], 'depth' => $previous['depth'] + 1, 'fingerprint' => $fingerprint, 'i' => $i, 'address_number' => self::get_address_number($i), 'chain_code' => $I_r, 'key' => $key); return count($address_definition) > 0 ? self::CKD(self::encode($data), $address_definition, $generated) : array(self::encode($data), implode('/', $generated)); }
public static function double(Point $p1) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { $p = $p1->curve->getPrime(); $a = $p1->curve->getA(); // $inverse = NumberTheory::inverse_mod(gmp_strval(gmp_mul(2, $p1->y)), $p); $inverse = gmp_strval(gmp_invert(gmp_strval(gmp_mul(2, $p1->y)), $p)); $three_x2 = gmp_mul(3, gmp_pow($p1->x, 2)); $l = gmp_strval(gmp_Utils::gmp_mod2(gmp_mul(gmp_add($three_x2, $a), $inverse), $p)); $x3 = gmp_strval(gmp_Utils::gmp_mod2(gmp_sub(gmp_pow($l, 2), gmp_mul(2, $p1->x)), $p)); $y3 = gmp_strval(gmp_Utils::gmp_mod2(gmp_sub(gmp_mul($l, gmp_sub($p1->x, $x3)), $p1->y), $p)); if (gmp_cmp(0, $y3) > 0) { $y3 = gmp_strval(gmp_add($p, $y3)); } $p3 = new Point($p1->curve, $x3, $y3); return $p3; } else { throw new ErrorException("Please install GMP"); } }
/** * Decode Mnemonic * * This function decodes a string of 12 words to convert to the electrum * seed. This is an implementation of http://tools.ietf.org/html/rfc1751, * which is how electrum generates a 128-bit key from 12 words. * * @param string $words * @return string */ public static function decode_mnemonic($words) { $words = explode(" ", $words); $out = ''; $n = 1626; for ($i = 0; $i < count($words) / 3; $i++) { $a = 3 * $i; list($word1, $word2, $word3) = array($words[$a], $words[$a + 1], $words[$a + 2]); $index_w1 = array_search($word1, self::$words); $index_w2 = array_search($word2, self::$words) % $n; $index_w3 = array_search($word3, self::$words) % $n; $x = $index_w1 + $n * \gmp_Utils::gmp_mod2($index_w2 - $index_w1, $n) + $n * $n * \gmp_Utils::gmp_mod2($index_w3 - $index_w2, $n); $out .= BitcoinLib::hex_encode($x); } return $out; }
function privkey2pubkey($ECDSA, $secp256k1_G) { // this is function that needs the phpecc stuff - rewrite when binary module available $privKey = gmp_Utils::gmp_hexdec($ECDSA); $pubKey = new PublicKey($secp256k1_G, Point::mul($privKey, $secp256k1_G)); $xcoord = strtoupper(gmp_Utils::gmp_dechex($pubKey->getPoint()->getX())); $xcoord = str_pad($xcoord, 64, '0', STR_PAD_LEFT); $ycoord = strtoupper(gmp_Utils::gmp_dechex($pubKey->getPoint()->getY())); $ycoord = str_pad($ycoord, 64, '0', STR_PAD_LEFT); return '04' . $xcoord . $ycoord; }
function BWWC__MATH_generate_bitcoin_address_from_mpk($master_public_key, $key_index) { if (USE_EXT != 'GMP' && USE_EXT != 'BCMATH') { return false; } /* if (USE_EXT == 'GMP') { $utils_class = 'gmp_Utils'; $fn_bchexdec = 'gmp_hexdec'; $fn_dec2base = 'gmp_dec2base'; $fn_base2dec = 'gmp_base2dec'; } else if (USE_EXT == 'BCMATH') { $utils_class = 'bcmath_Utils'; $fn_bchexdec = 'bchexdec'; $fn_dec2base = 'dec2base'; $fn_base2dec = 'base2dec'; } else return false; */ // create the ecc curve if (USE_EXT == 'GMP') { // GMP $_p = gmp_Utils::gmp_hexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'); $_r = gmp_Utils::gmp_hexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'); $_b = gmp_Utils::gmp_hexdec('0x0000000000000000000000000000000000000000000000000000000000000007'); $_Gx = gmp_Utils::gmp_hexdec('0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'); $_Gy = gmp_Utils::gmp_hexdec('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'); } else { // BCMATH $_p = bcmath_Utils::bchexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'); $_r = bcmath_Utils::bchexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'); $_b = bcmath_Utils::bchexdec('0x0000000000000000000000000000000000000000000000000000000000000007'); $_Gx = bcmath_Utils::bchexdec('0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798'); $_Gy = bcmath_Utils::bchexdec('0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'); } $curve = new CurveFp($_p, 0, $_b); $gen = new Point($curve, $_Gx, $_Gy, $_r); // prepare the input values if (USE_EXT == 'GMP') { // GMP $x = gmp_Utils::gmp_hexdec('0x' . substr($master_public_key, 0, 64)); $y = gmp_Utils::gmp_hexdec('0x' . substr($master_public_key, 64, 64)); $z = gmp_Utils::gmp_hexdec('0x' . hash('sha256', hash('sha256', $key_index . ':0:' . pack('H*', $master_public_key), TRUE))); } else { // BCMATH $x = bcmath_Utils::bchexdec('0x' . substr($master_public_key, 0, 64)); $y = bcmath_Utils::bchexdec('0x' . substr($master_public_key, 64, 64)); $z = bcmath_Utils::bchexdec('0x' . hash('sha256', hash('sha256', $key_index . ':0:' . pack('H*', $master_public_key), TRUE))); } // generate the new public key based off master and sequence points $pt = Point::add(new Point($curve, $x, $y), Point::mul($z, $gen)); if (USE_EXT == 'GMP') { // GMP $keystr = "" . str_pad(gmp_Utils::gmp_dec2base($pt->getX(), 256), 32, "", STR_PAD_LEFT) . str_pad(gmp_Utils::gmp_dec2base($pt->getY(), 256), 32, "", STR_PAD_LEFT); } else { // BCMATH $keystr = "" . str_pad(bcmath_Utils::dec2base($pt->getX(), 256), 32, "", STR_PAD_LEFT) . str_pad(bcmath_Utils::dec2base($pt->getY(), 256), 32, "", STR_PAD_LEFT); } $vh160 = "" . hash('ripemd160', hash('sha256', $keystr, TRUE), TRUE); $addr = $vh160 . substr(hash('sha256', hash('sha256', $vh160, TRUE), TRUE), 0, 4); // base58 conversion $alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'; $encoded = ''; if (USE_EXT == 'GMP') { // GMP $num = gmp_Utils::gmp_base2dec($addr, 256); } else { // BCMATH $num = bcmath_Utils::base2dec($addr, 256); } while (intval($num) >= 58) { $div = bcdiv($num, '58'); $mod = bcmod($num, '58'); $encoded = $alphabet[intval($mod)] . $encoded; $num = $div; } $encoded = $alphabet[intval($num)] . $encoded; $pad = ''; $n = 0; while ($addr[$n++] == "") { $pad .= '1'; } return $pad . $encoded; }
public static function secp256k1_params() { if (extension_loaded('gmp') && USE_EXT == 'GMP') { return array('p' => gmp_Utils::gmp_hexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'), 'a' => gmp_Utils::gmp_hexdec('0x0000000000000000000000000000000000000000000000000000000000000000'), 'b' => gmp_Utils::gmp_hexdec('0x0000000000000000000000000000000000000000000000000000000000000007'), 'n' => gmp_Utils::gmp_hexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'), 'x' => gmp_Utils::gmp_hexdec("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"), 'y' => gmp_Utils::gmp_hexdec("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { return array('p' => bcmath_Utils::bchexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F'), 'a' => bcmath_Utils::bchexdec('0x0000000000000000000000000000000000000000000000000000000000000000'), 'b' => bcmath_Utils::bchexdec('0x0000000000000000000000000000000000000000000000000000000000000007'), 'n' => bcmath_Utils::bchexdec('0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141'), 'x' => bcmath_Utils::bchexdec("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"), 'y' => bcmath_Utils::bchexdec("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8")); } } }
public function decompress_public_key($key) { // Initialize $y_byte = substr($key, 0, 2); $x_coordinate = substr($key, 2); // Set variables $x = gmp_strval(gmp_init($x_coordinate, 16), 10); $curve = SECcurve::curve_secp256k1(); $generator = SECcurve::generator_secp256k1(); // Decode try { $x3 = NumberTheory::modular_exp($x, 3, $curve->getPrime()); $y2 = gmp_add($x3, $curve->getB()); $y0 = NumberTheory::square_root_mod_prime(gmp_strval($y2, 10), $curve->getPrime()); if ($y0 === false) { return false; } $y1 = gmp_strval(gmp_sub($curve->getPrime(), $y0), 10); $y_coordinate = $y_byte == '02' ? gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) == '0' ? $y0 : $y1 : (gmp_Utils::gmp_mod2(gmp_init($y0, 10), 2) !== '0' ? $y0 : $y1); $y_coordinate = str_pad(gmp_strval($y_coordinate, 16), 64, '0', STR_PAD_LEFT); $point = new Point($curve, gmp_strval(gmp_init($x_coordinate, 16), 10), gmp_strval(gmp_init($y_coordinate, 16), 10), $generator->getOrder()); } catch (Exception $e) { return false; } // Return return array('x' => $x_coordinate, 'y' => $y_coordinate, 'point' => $point, 'public_key' => '04' . $x_coordinate . $y_coordinate); }