/** * 添加person */ public function add($person) { $ret = false; $point = new Point(); $now_id = (int) $point->add($person['now']['lng'], $person['now']['lat'], $person['now']['zoom']); $want_id = (int) $point->add($person['want']['lng'], $person['want']['lat'], $person['want']['zoom']); $mysql = new MysqlAccess(); if ($now_id > 0 && $want_id > 0) { $sql = "insert into person(`name`, `now`, `want`, `state`, `description`) values " . "('{$person['name']}', {$now_id}, {$want_id}, '{$person['state']}', '{$person['description']}')"; $mysql->runSql($sql); $ret = true; } return $ret; }
/** * @test */ public function testAdd_AddPointIsMinus() { $addPoint = -15; $point = new Point(10); $point->add($addPoint); $this->assertThat($point->getPoint(), $this->equalTo(10), '0ポイント未満を足す'); }
/** * @covers tarcisio\p2d\Point::add */ public function testAdd() { $p1 = new Point(10, 10); $p2 = new Point(30, 30); $p3 = $p1->add($p2); $this->assertEquals($p3->x, $p1->x + $p2->x); $this->assertEquals($p3->y, $p1->y + $p2->y); }
/** * 添加一个楼盘到数据库 * @param $premises Array(name, type, description, project_id, state, area, structure, lng, lat, zoom) * @return bool 是否成功 */ public function add($premises) { $ret = false; $point = new Point(); $point_id = (int) $point->add($premises['lng'], $premises['lat'], $premises['zoom']); $mysql = new MysqlAccess(); if ($point_id > 0) { $sql = "insert into premises(`name`, `description`, `point_id`, `project_id`) " . "values('{$premises['name']}', '{$premises['description']}', {$point_id}, " . "{$premises['project_id']})"; $mysql->runSql($sql); $ret = true; } return $ret; }
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"); } }
function recoverPubKey($r, $s, $e, $recoveryFlags, $G) { $isYEven = ($recoveryFlags & 1) != 0; $isSecondKey = ($recoveryFlags & 2) != 0; $curve = $G->getCurve(); $signature = new Signature($r, $s); // Precalculate (p + 1) / 4 where p is the field order static $p_over_four; // XXX just assuming only one curve/prime will be used if (!$p_over_four) { $p_over_four = gmp_div(gmp_add($curve->getPrime(), 1), 4); } // 1.1 Compute x if (!$isSecondKey) { $x = $r; } else { $x = gmp_add($r, $G->getOrder()); } // 1.3 Convert x to point $alpha = gmp_mod(gmp_add(gmp_add(gmp_pow($x, 3), gmp_mul($curve->getA(), $x)), $curve->getB()), $curve->getPrime()); $beta = NumberTheory::modular_exp($alpha, $p_over_four, $curve->getPrime()); // If beta is even, but y isn't or vice versa, then convert it, // otherwise we're done and y == beta. if (isBignumEven($beta) == $isYEven) { $y = gmp_sub($curve->getPrime(), $beta); } else { $y = $beta; } // 1.4 Check that nR is at infinity (implicitly done in construtor) $R = new Point($curve, $x, $y, $G->getOrder()); $point_negate = function ($p) { return new Point($p->curve, $p->x, gmp_neg($p->y), $p->order); }; // 1.6.1 Compute a candidate public key Q = r^-1 (sR - eG) $rInv = NumberTheory::inverse_mod($r, $G->getOrder()); $eGNeg = $point_negate(Point::mul($e, $G)); $Q = Point::mul($rInv, Point::add(Point::mul($s, $R), $eGNeg)); // 1.6.2 Test Q as a public key $Qk = new PublicKey($G, $Q); if ($Qk->verifies($e, $signature)) { return $Qk; } return false; }
function addr_from_mpk($mpk, $index) { // create the ecc curve $_p = gmp_init('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16); $_r = gmp_init('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16); $_b = gmp_init('0000000000000000000000000000000000000000000000000000000000000007', 16); $_Gx = gmp_init('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16); $_Gy = gmp_init('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16); $curve = new Curve($_p, 0, $_b); $gen = new Point($curve, $_Gx, $_Gy, $_r); // prepare the input values $x = gmp_init(substr($mpk, 0, 64), 16); $y = gmp_init(substr($mpk, 64, 64), 16); $z = gmp_init(hash('sha256', hash('sha256', $index . ':0:' . pack('H*', $mpk), TRUE)), 16); // generate the new public key based off master and sequence points $pt = Point::add(new Point($curve, $x, $y), Point::mul($z, $gen)); $keystr = pack('H*', '04' . str_pad(gmp_strval($pt->x, 16), 64, '0', STR_PAD_LEFT) . str_pad(gmp_strval($pt->y, 16), 64, '0', STR_PAD_LEFT)); $vh160 = '00' . hash('ripemd160', hash('sha256', $keystr, TRUE)); $addr = $vh160 . substr(hash('sha256', hash('sha256', pack('H*', $vh160), TRUE)), 0, 8); $num = gmp_strval(gmp_init($addr, 16), 58); $num = strtr($num, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv', '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'); $pad = ''; $n = 0; while ($addr[$n] == '0' && $addr[$n + 1] == '0') { $pad .= '1'; $n += 2; } return $pad . $num; }
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 static function test_add(CurveFp $c, $x1, $y1, $x2, $y2, $x3, $y3, $verbose = false) { if (extension_loaded('gmp') && USE_EXT == 'GMP') { // expect that on curve c, (x1, y1) + (x2, y2) = (x3, y3) $p1 = new Point($c, $x1, $y1); $p2 = new Point($c, $x2, $y2); $p3 = Point::add($p1, $p2); if ($verbose) { echo $p1 . " + " . $p2 . " = " . $p3; } if (gmp_Utils::gmp_mod2($p3->getX(), 23) != $x3 || gmp_Utils::gmp_mod2($p3->getY(), 23) != $y3) { echo " ADD TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " ADD TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } else { if (extension_loaded('bcmath') && USE_EXT == 'BCMATH') { // expect that on curve c, (x1, y1) + (x2, y2) = (x3, y3) $p1 = new Point($c, $x1, $y1); $p2 = new Point($c, $x2, $y2); $p3 = Point::add($p1, $p2); if ($verbose) { echo $p1 . " + " . $p2 . " = " . $p3; } if (bcmod($p3->getX(), 23) != $x3 || bcmod($p3->getY(), 23) != $y3) { echo " ADD TEST FAILURE: should give: (" . $x3 . " , " . $y3 . ")<br /><br /><br />"; flush(); } else { if ($verbose) { echo " ADD TEST SUCCESSFUL<br /><br /><br />"; } flush(); } } } }
public function CKD($master, $address_definition, $generated = array()) { // Import master $previous = $this->import($master); // Check key type if ($previous['type'] == 'private') { $private_key = $previous['key']; $public_key = $this->private_to_public($private_key, true); } else { if ($previous['type'] == 'public') { $public_key = $previous['key']; } else { return false; } } // Get fingerprint $fingerprint = substr(hash('ripemd160', hash('sha256', pack("H*", $public_key), true)), 0, 8); $i = array_pop($address_definition); // Check prime $is_prime = gmp_cmp(gmp_init($i, 16), gmp_init('80000000', 16)) == -1 ? 0 : 1; if ($is_prime == 1) { if ($previous['type'] == 'public') { return false; } $data = '00' . $private_key . $i; } else { if ($is_prime == 0) { $data = $public_key . $i; } } // Hash data 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); // Initialize curve $g = SECcurve::generator_secp256k1(); $n = $g->getOrder(); // Generate key if ($previous['type'] == 'private') { $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') { $decompressed = $this->decompress_public_key($public_key); $curve = SECcurve::curve_secp256k1(); $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 = '04' . $new_x . $new_y; $key = '0' . (gmp_Utils::gmp_mod2(gmp_init(substr($key, 66, 64), 16), 2) == 0 ? '2' : '3') . substr($key, 2, 64); //$key = preg_replace("/^04/", "", $key); } } if (!isset($key)) { return FALSE; } // Set data $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' => $this->get_address_number($i), 'chain_code' => $I_r, 'key' => $key); // Return if (count($address_definition) > 0) { return $this->CKD($this->encode($data), $address_definition, $generated); } else { return array($this->encode($data), implode('/', $generated)); } }
/** * Public Key From MPK * * This function is used to generate a public key from the supplied * $mpk - the master public key, and an $iteration indicating which * address in the sequence should be generated. * * @param string $mpk * @param int $iteration * @return string */ public static function public_key_from_mpk($mpk, $iteration, $change = 0, $compressed = FALSE) { $change = $change == 0 ? '0' : '1'; // Generate the curve, and the generator point. $curve = \SECcurve::curve_secp256k1(); $gen = \SECcurve::generator_secp256k1(); // Prepare the input values, by converting the MPK to X and Y coordinates $x = gmp_init(substr($mpk, 0, 64), 16); $y = gmp_init(substr($mpk, 64, 64), 16); // Generate a scalar from the $iteration and $mpk $z = gmp_init(hash('sha256', hash('sha256', "{$iteration}:{$change}:" . pack('H*', $mpk), TRUE)), 16); try { // Add the Point defined by $x and $y, to the result of EC multiplication of $z by $gen $pt = \Point::add(new \Point($curve, $x, $y), \Point::mul($z, $gen)); // Generate the uncompressed public key. $keystr = '04' . str_pad(gmp_strval($pt->x, 16), 64, '0', STR_PAD_LEFT) . str_pad(gmp_strval($pt->y, 16), 64, '0', STR_PAD_LEFT); } catch (Exception $e) { throw new ErrorException($e->getMessage()); } return $compressed == TRUE ? BitcoinLib::compress_public_key($keystr) : $keystr; }
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; }
/** * 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)); }