/** * Generate a number that lies between 0 and q-1. * * @param Math_BigInteger $q Max number. * * @return Math_BigInteger Generated number. */ public static function randomNumber($q) { $bytes = strlen($q->toBytes()) + 8; $ints = $bytes + 1 >> 2; $cstring = crypt_random_string($ints); $random = ''; for ($i = 0; $i < $ints; ++$i) { $random .= pack('N', $cstring[$i]); } $c = new Math_BigInteger(substr($random, 0, $bytes), 256); $one = new Math_BigInteger(1); $result_base = $c->divide($q->subtract($one)); return $result_base[1]->add($one); }
/** * @param string $decimal 128bit int * @return string IPv4 or IPv6 */ public static function inet_itop($decimal) { // QuickFix: Decimal 0 is both for ::0 and 0.0.0.0, however it defaults to IPv6, while there is now way a // ::/64 will ever be used. if ($decimal < 255) { return '0.0.0.' . $decimal; } $parts = array(); // Use BCMath if available if (function_exists('bcadd')) { $parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0); $decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336')); $parts[2] = bcdiv($decimal, '18446744073709551616', 0); $decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616')); $parts[3] = bcdiv($decimal, '4294967296', 0); $decimal = bcsub($decimal, bcmul($parts[3], '4294967296')); $parts[4] = $decimal; } else { // Otherwise use the pure PHP BigInteger class $decimal = new Math_BigInteger($decimal); list($parts[1], ) = $decimal->divide(new Math_BigInteger('79228162514264337593543950336')); $decimal = $decimal->subtract($parts[1]->multiply(new Math_BigInteger('79228162514264337593543950336'))); list($parts[2], ) = $decimal->divide(new Math_BigInteger('18446744073709551616')); $decimal = $decimal->subtract($parts[2]->multiply(new Math_BigInteger('18446744073709551616'))); list($parts[3], ) = $decimal->divide(new Math_BigInteger('4294967296')); $decimal = $decimal->subtract($parts[3]->multiply(new Math_BigInteger('4294967296'))); $parts[4] = $decimal; $parts[1] = $parts[1]->toString(); $parts[2] = $parts[2]->toString(); $parts[3] = $parts[3]->toString(); $parts[4] = $parts[4]->toString(); } foreach ($parts as &$part) { // convert any signed ints to unsigned for pack // this should be fine as it will be treated as a float if ($part > 2147483647) { $part -= 4294967296.0; } } $ip = inet_ntop(pack('N4', $parts[1], $parts[2], $parts[3], $parts[4])); // fix IPv4 by removing :: from the beginning if (strpos($ip, '.') !== false) { return substr($ip, 2); } return $ip; }
/** * Returns part of number $num, starting at bit * position $start with length $length * * @param gmp resource $num * @param int start * @param int length * @return gmp resource * @access public */ function subint($num, $start, $length) { $start_byte = intval($start / 8); $start_bit = $start % 8; $byte_length = intval($length / 8); $bit_length = $length % 8; if ($bit_length) { $byte_length++; } $bi = new Math_BigInteger($num, 10); $divider = new Math_BigInteger(1 << $start_bit); $res = $bi->divide($divider); $bi = $res[0]; $tmp = _byte_strrev(_byte_substr($bi->toBytes(), $start_byte, $byte_length)); $tmp = str_pad($tmp, $byte_length, ""); $tmp = _byte_substr_replace($tmp, $tmp[$byte_length - 1] & _byte_chr(0xff >> 8 - $bit_length), $byte_length - 1, 1); return $this->bin2int($tmp); }
if (!$CheckShareData) { $fixed_diff = floatval($hash_rate); } else { $fixed_diff = floatval($hash_rate * $CheckShareData * 4); } $fixed_diff = $fixed_diff * $miner_diff; $fixed_diff = new Math_BigInteger($fixed_diff); $current .= "\nFixed diff value:" . $fixed_diff; } else { die('You need to specify your hashrate!'); } $a256 = new Math_BigInteger('115792089237316195423570985008687907853269984665640564039457584007913129639936'); //2^256 //Convert diff decimal to hex 256bit $new_block_diff = new Math_BigInteger($fixed_diff); list($quotient, $remainder) = $a256->divide($new_block_diff); $target_diff = $quotient->toString(); $target_diff = bcdechex($target_diff); $currentLenght = strlen($target_diff); $desiredLenght = 64; if ($currentLenght < $desiredLenght) { $toadd = $desiredLenght - $currentLenght; for ($i = 0; $i < $toadd; $i++) { $fix .= '0'; } $target_diff = '0x' . $fix . $target_diff; } //Save Getwork for user to validate later with submit work $appKey = md5($hash_rate . $payout_addr); $current .= "\nAPPKEY:" . $appKey; $block_number = hexdec($block_number) + 1;
/** * Generate a random number * * Returns a random number between $min and $max where $min and $max * can be defined using one of the two methods: * * $min->random($max) * $max->random($min) * * @param Math_BigInteger $arg1 * @param Math_BigInteger $arg2 * @return Math_BigInteger * @access public * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a Math_BigInteger object. * That method is still supported for BC purposes. */ function random($arg1, $arg2 = false) { if ($arg1 === false) { return false; } if ($arg2 === false) { $max = $arg1; $min = $this; } else { $min = $arg1; $max = $arg2; } $compare = $max->compare($min); if (!$compare) { return $this->_normalize($min); } elseif ($compare < 0) { // if $min is bigger then $max, swap $min and $max $temp = $max; $max = $min; $min = $temp; } static $one; if (!isset($one)) { $one = new Math_BigInteger(1); } $max = $max->subtract($min->subtract($one)); $size = strlen(ltrim($max->toBytes(), chr(0))); /* doing $random % $max doesn't work because some numbers will be more likely to occur than others. eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145 would produce 5 whereas the only value of random that could produce 139 would be 139. ie. not all numbers would be equally likely. some would be more likely than others. creating a whole new random number until you find one that is within the range doesn't work because, for sufficiently small ranges, the likelihood that you'd get a number within that range would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability would be pretty high that $random would be greater than $max. phpseclib works around this using the technique described here: http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string */ $random_max = new Math_BigInteger(chr(1) . str_repeat("", $size), 256); $random = $this->_random_number_helper($size); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); while ($random->compare($max_multiple) >= 0) { $random = $random->subtract($max_multiple); $random_max = $random_max->subtract($max_multiple); $random = $random->bitwise_leftShift(8); $random = $random->add($this->_random_number_helper(1)); $random_max = $random_max->bitwise_leftShift(8); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); } list(, $random) = $random->divide($max); return $this->_normalize($random->add($min)); }
/** * Prepare a number for use in Montgomery Modular Reductions * * @see _montgomery() * @see _slidingWindow() * @access private * @param Array $x * @param Array $n * @return Array */ function _prepMontgomery($x, $n) { $lhs = new Math_BigInteger(); $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x); $rhs = new Math_BigInteger(); $rhs->value = $n; list(, $temp) = $lhs->divide($rhs); return $temp->value; }
/** * Barrett Modular Reduction * * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, * so as not to require negative numbers (initially, this script didn't support negative numbers). * * @see _slidingWindow() * @access private * @param Math_BigInteger * @return Math_BigInteger */ function _barrett($n) { static $cache; $n_length = count($n->value); if (!isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE])) { $cache[MATH_BIGINTEGER_VARIABLE] = $n; $temp = new Math_BigInteger(); $temp->value = $this->_array_repeat(0, 2 * $n_length); $temp->value[] = 1; list($cache[MATH_BIGINTEGER_DATA], ) = $temp->divide($n); } $temp = new Math_BigInteger(); $temp->value = array_slice($this->value, $n_length - 1); $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA]); $temp->value = array_slice($temp->value, $n_length + 1); $result = new Math_BigInteger(); $result->value = array_slice($this->value, 0, $n_length + 1); $temp = $temp->multiply($n); $temp->value = array_slice($temp->value, 0, $n_length + 1); if ($result->compare($temp) < 0) { $corrector = new Math_BigInteger(); $corrector->value = $this->_array_repeat(0, $n_length + 1); $corrector->value[] = 1; $result = $result->add($corrector); } $result = $result->subtract($temp); while ($result->compare($n) > 0) { $result = $result->subtract($n); } return $result; }
/** * Barrett Modular Reduction * * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly, * so as not to require negative numbers (initially, this script didn't support negative numbers). * * @see _slidingWindow() * @access private * @param Math_BigInteger * @return Math_BigInteger */ function _barrett($n) { static $cache = array(MATH_BIGINTEGER_VARIABLE => array(), MATH_BIGINTEGER_DATA => array()); $n_length = count($n->value); if (count($this->value) > 2 * $n_length) { list(, $temp) = $this->divide($n); return $temp; } if (($key = array_search($n->value, $cache[MATH_BIGINTEGER_VARIABLE])) === false) { $key = count($cache[MATH_BIGINTEGER_VARIABLE]); $cache[MATH_BIGINTEGER_VARIABLE][] = $n->value; $temp = new Math_BigInteger(); $temp->value = $this->_array_repeat(0, 2 * $n_length); $temp->value[] = 1; list($cache[MATH_BIGINTEGER_DATA][], ) = $temp->divide($n); } $temp = new Math_BigInteger(); $temp->value = array_slice($this->value, $n_length - 1); $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA][$key]); $temp->value = array_slice($temp->value, $n_length + 1); $result = new Math_BigInteger(); $result->value = array_slice($this->value, 0, $n_length + 1); $temp = $temp->_multiplyLower($n, $n_length + 1); // $temp->value == array_slice($temp->multiply($n)->value, 0, $n_length + 1) if ($result->compare($temp) < 0) { $corrector = new Math_BigInteger(); $corrector->value = $this->_array_repeat(0, $n_length + 1); $corrector->value[] = 1; $result = $result->add($corrector); } $result = $result->subtract($temp); while ($result->compare($n) > 0) { $result = $result->subtract($n); } return $result; }
echo "\$z = {$z};\r\n"; echo "\r\n"; $result = bcadd($x, $y); $_result = $_x->add($_y); echo "\$result = \$x+\$y;\r\n"; echo "{$result}\r\n"; echo $_result->toString(); echo "\r\n\r\n"; $result = bcsub($result, $y); $_result = $_result->subtract($_y); echo "\$result = \$result-\$y;\r\n"; echo "{$result}\r\n"; echo $_result->toString(); echo "\r\n\r\n"; $result = bcdiv($x, $y); list($_result, ) = $_x->divide($_y); echo "\$result = \$x/\$y;\r\n"; echo "{$result}\r\n"; echo $_result->toString(); echo "\r\n\r\n"; $result = bcmod($y, $z); list(, $_result) = $_y->divide($_z); echo "\$result = \$x%\$y;\r\n"; echo "{$result}\r\n"; echo $_result->toString(); echo "\r\n\r\n"; $result = bcmul($x, $z); $_result = $_x->multiply($_z); echo "\$result = \$x*\$z;\r\n"; echo "{$result}\r\n"; echo $_result->toString();
function inet_itop($decimal) { $parts = array(); // use BCMath if the extension exists if (function_exists('bcadd')) { $parts[1] = bcdiv($decimal, '79228162514264337593543950336', 0); $decimal = bcsub($decimal, bcmul($parts[1], '79228162514264337593543950336')); $parts[2] = bcdiv($decimal, '18446744073709551616', 0); $decimal = bcsub($decimal, bcmul($parts[2], '18446744073709551616')); $parts[3] = bcdiv($decimal, '4294967296', 0); $decimal = bcsub($decimal, bcmul($parts[3], '4294967296')); $parts[4] = $decimal; } else { $decimal = new Math_BigInteger($decimal); list($parts[1], ) = $decimal->divide(new Math_BigInteger('79228162514264337593543950336')); $decimal = $decimal->subtract($parts[1]->multiply(new Math_BigInteger('79228162514264337593543950336'))); list($parts[2], ) = $decimal->divide(new Math_BigInteger('18446744073709551616')); $decimal = $decimal->subtract($parts[2]->multiply(new Math_BigInteger('18446744073709551616'))); list($parts[3], ) = $decimal->divide(new Math_BigInteger('4294967296')); $decimal = $decimal->subtract($parts[3]->multiply(new Math_BigInteger('4294967296'))); $parts[4] = $decimal; $parts[1] = $parts[1]->toString(); $parts[2] = $parts[2]->toString(); $parts[3] = $parts[3]->toString(); $parts[4] = $parts[4]->toString(); } foreach ($parts as &$part) { // convert any signed ints to unsigned for pack // this should be fine as it will be treated as a float if ($part > 2147483647) { $part -= 4294967296; } } $ip = inet_ntop(pack('N4', $parts[1], $parts[2], $parts[3], $parts[4])); // fix IPv4 by removing :: from the beginning if (strpos($ip, '.') !== false) { return substr($ip, 2); } return $ip; }
/** * Divide two arbitrary precision numbers * * @param string $a The left operand, as a string. * @param string $b The right operand, as a string. * @access public * @return string|null Returns the result of the division as a string, or <b>NULL</b> if right_operand is 0. */ public function div($a, $b) { $a = new Math_BigInteger($a); $b = new Math_BigInteger($b); list($quotient, ) = $a->divide($b); return $quotient->toString(); }
/** * Converts a 128bit int to a human readable representation. * * Requires PHP to be compiled with IPv6 support. * This could be made to work without IPv6 support but * I don't think there would be much use for it if PHP * doesn't support IPv6. * * @author Sam Clarke * @link http://www.samclarke.com/2011/07/php-ipv6-to-128bit-int/ * @param string $decimal 128bit int * @return string IPv4 or IPv6 */ protected static function decimalToIp($decimal) { $parts = array(); $decimal = new BigInteger($decimal); list($parts[1], ) = $decimal->divide(new BigInteger('79228162514264337593543950336')); $decimal = $decimal->subtract($parts[1]->multiply(new BigInteger('79228162514264337593543950336'))); list($parts[2], ) = $decimal->divide(new BigInteger('18446744073709551616')); $decimal = $decimal->subtract($parts[2]->multiply(new BigInteger('18446744073709551616'))); list($parts[3], ) = $decimal->divide(new BigInteger('4294967296')); $decimal = $decimal->subtract($parts[3]->multiply(new BigInteger('4294967296'))); $parts[4] = $decimal; $parts[1] = $parts[1]->toString(); $parts[2] = $parts[2]->toString(); $parts[3] = $parts[3]->toString(); $parts[4] = $parts[4]->toString(); foreach ($parts as &$part) { // convert any signed ints to unsigned for pack // this should be fine as it will be treated as a float if ($part > 2147483647) { $part -= 4294967296; } } $ip = inet_ntop(pack('N4', $parts[1], $parts[2], $parts[3], $parts[4])); // fix IPv4 by removing :: from the beginning if (strpos($ip, '.') !== false) { return substr($ip, 2); } return $ip; }