Implemented root and pow functions in the BigInteger lib, made some changes to support update PHPStruct lib
This commit is contained in:
parent
652327fecd
commit
9e08e6fe8f
2
TL.php
2
TL.php
@ -68,7 +68,7 @@ class TL
|
||||
$this->method_id[$z->id] = $z;
|
||||
$this->method_name[$z->method] = $z;
|
||||
}
|
||||
$this->struct = new \danog\PHP\Struct();
|
||||
$this->struct = new \danog\PHP\StructClass();
|
||||
}
|
||||
|
||||
public function serialize_obj($type_, $kwargs)
|
||||
|
67
mtproto.php
67
mtproto.php
@ -7,7 +7,7 @@ require_once 'crypt.php';
|
||||
require_once 'prime.php';
|
||||
require_once 'TL.php';
|
||||
require_once 'vendor/autoload.php';
|
||||
$struct = new \danog\PHP\Struct();
|
||||
$struct = new \danog\PHP\StructClass();
|
||||
/**
|
||||
* Function to get hex crc32
|
||||
* :param data: Data to encode.
|
||||
@ -101,59 +101,6 @@ function fopen_and_write($filename, $mode, $data)
|
||||
|
||||
return $handle;
|
||||
}
|
||||
/**
|
||||
* long_to_bytes(n:long, blocksize:int) : string
|
||||
* Convert a long integer to a byte string.
|
||||
* If optional blocksize is given and greater than zero, pad the front of the
|
||||
* byte string with binary zeros so that the length is a multiple of
|
||||
* blocksize.
|
||||
*/
|
||||
function long_to_bytes($n, $blocksize = 0)
|
||||
{
|
||||
$s = null;
|
||||
$n = (float) $n;
|
||||
while ($n > 0) {
|
||||
$s = $GLOBALS['struct']->pack('I', $n & 4294967295).$s;
|
||||
$n = $n >> 32;
|
||||
}
|
||||
$break = false;
|
||||
foreach (pyjslib_range(strlen($s)) as $i) {
|
||||
if ($s[$i] != string2bin('\000')[0]) {
|
||||
$break = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$break) {
|
||||
$s = string2bin('\000');
|
||||
$i = 0;
|
||||
}
|
||||
$s = substr($s, $i);
|
||||
if ($blocksize > 0 && strlen($s) % $blocksize) {
|
||||
$s = pack('@'.$blocksize - (strlen($s) % $blocksize)).$s;
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
/**
|
||||
* bytes_to_long(string) : long
|
||||
* Convert a byte string to a long integer.
|
||||
* This is (essentially) the inverse of long_to_bytes().
|
||||
*/
|
||||
function bytes_to_long($s)
|
||||
{
|
||||
$acc = 0;
|
||||
$length = strlen($s);
|
||||
if ($length % 4) {
|
||||
$extra = (4 - ($length % 4));
|
||||
$s = pack('@'.$extra).$s;
|
||||
$length += $extra;
|
||||
}
|
||||
foreach (pyjslib_range(0, $length, 4) as $i) {
|
||||
$acc = ($acc << 32) + $GLOBALS['struct']->unpack('>I', substr($s, $i, 4))[0];
|
||||
}
|
||||
|
||||
return $acc;
|
||||
}
|
||||
function string2bin($string)
|
||||
{
|
||||
$res = null;
|
||||
@ -204,8 +151,7 @@ class Session
|
||||
*/
|
||||
public function send_message($message_data)
|
||||
{
|
||||
$message_id = long_to_bytes((int) ((time() + $this->timedelta) * pow(2, 30)) * 4);
|
||||
//$message_id = $this->struct->pack('<Q', (int) ((time() + $this->timedelta) * pow(2, 30)) * 4);
|
||||
$message_id = $this->struct->pack('<Q', (int) ((time() + $this->timedelta) * pow(2, 30)) * 4);
|
||||
|
||||
if (($this->auth_key == null) || ($this->server_salt == null)) {
|
||||
$message = string2bin('\x00\x00\x00\x00\x00\x00\x00\x00').$message_id.$this->struct->pack('<I', strlen($message_data)).$message_data;
|
||||
@ -219,7 +165,6 @@ class Session
|
||||
$message = $this->auth_key_id.$message_key.crypt::ige_encrypt($encrypted_data.$padding, $aes_key, $aes_iv);
|
||||
}
|
||||
$step1 = $this->struct->pack('<II', (strlen($message) + 12), $this->number).$message;
|
||||
var_dump(newcrc32($step1));
|
||||
$step2 = $step1.$this->struct->pack('<I', newcrc32($step1));
|
||||
fwrite($this->sock, $step2);
|
||||
$this->number += 1;
|
||||
@ -266,7 +211,6 @@ class Session
|
||||
{
|
||||
foreach (range(1, $this->MAX_RETRY) as $i) {
|
||||
try {
|
||||
//var_dump(py2php_kwargs_function_call('serialize_method', [$method], $kwargs));
|
||||
$this->send_message($this->tl->serialize_method($method, $kwargs));
|
||||
$server_answer = $this->recv_message();
|
||||
} catch (Exception $e) {
|
||||
@ -287,7 +231,6 @@ class Session
|
||||
$public_key_fingerprint = $ResPQ['server_public_key_fingerprints'][0];
|
||||
$pq_bytes = $ResPQ['pq'];
|
||||
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
|
||||
|
||||
var_dump($this->PrimeModule->primefactors($pq));
|
||||
die;
|
||||
var_dump($this->PrimeModule->pollard_brent(15));
|
||||
@ -300,9 +243,9 @@ class Session
|
||||
}
|
||||
assert((($p * $q) == $pq) && ($p < $q));
|
||||
pyjslib_printnl(sprintf('Factorization %d = %d * %d', [$pq, $p, $q]));
|
||||
$p_bytes = long_to_bytes($p);
|
||||
$q_bytes = long_to_bytes($q);
|
||||
$f = pyjslib_open(__DIR__.'/rsa.pub');
|
||||
$p_bytes = $this->struct->pack('>Q', $p);
|
||||
$q_bytes = $this->struct->pack('>Q', $q);
|
||||
$f = file_get_contents(__DIR__.'/rsa.pub');
|
||||
$key = RSA::importKey($f->read());
|
||||
$new_nonce = random_bytes(32);
|
||||
$data = py2php_kwargs_function_call('serialize_obj', ['p_q_inner_data'], ['pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce]);
|
||||
|
@ -120,12 +120,9 @@ class PrimeModule
|
||||
public function primefactors($n, $sort = false)
|
||||
{
|
||||
$factors = [];
|
||||
if ($n->compare(PHP_INT_MAX) === -1) {
|
||||
var_dump((int) $n->toString());
|
||||
}
|
||||
$limit = ((int) (pow($n, 0.5)) + 1);
|
||||
$limit = $n->root()->add(1);
|
||||
foreach ($this->smallprimes as $checker) {
|
||||
if (($checker > $limit)) {
|
||||
if (($limit < $checker)) {
|
||||
break;
|
||||
}
|
||||
while (($n % $checker) == 0) {
|
||||
|
13
sqr.php
Normal file
13
sqr.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
function mysqr($n) {
|
||||
$guess = $n / 2;
|
||||
while (true) {
|
||||
$last = $guess;
|
||||
$guess = (($n / $guess) + $guess) / 2;
|
||||
if($last == $guess) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $guess;
|
||||
}
|
||||
var_dump(mysqr(234892482328),sqrt(234892482328));
|
@ -1573,7 +1573,166 @@ class BigInteger
|
||||
|
||||
return array($this->_normalize($quotient), $this->_normalize($x));
|
||||
}
|
||||
/**
|
||||
* Calculates the nth root of a biginteger.
|
||||
*
|
||||
* Returns the nth root of a positive biginteger, where n defaults to 2
|
||||
*
|
||||
* Here's an example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $a = new \phpseclib\Math\BigInteger('625');
|
||||
*
|
||||
* $root = $a->root();
|
||||
*
|
||||
* echo $root->toString(); // outputs 25
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @param \phpseclib\Math\BigInteger $n
|
||||
* @return \phpseclib\Math\BigInteger
|
||||
* @access public
|
||||
* @internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}.
|
||||
*/
|
||||
function root($n = null)
|
||||
{
|
||||
$one = new static(1);
|
||||
$two = new static(2);
|
||||
if($n === null) $n = $two;
|
||||
if ($n->compare($one) == -1) return new static(0); // we want positive exponents
|
||||
if ($this->compare($one) == -1) return new static(0); // we want positive numbers
|
||||
if ($this->compare($two) == -1) return $one; // n-th root of 1 or 2 is 1
|
||||
$root = new static();
|
||||
switch (MATH_BIGINTEGER_MODE) {
|
||||
case self::MODE_GMP:
|
||||
$root->value = gmp_root($this->value, $n->value);
|
||||
break;
|
||||
case self::MODE_BCMATH:
|
||||
// g is our guess number
|
||||
$g = 2;
|
||||
// while (g^n < num) g=g*2
|
||||
while (bccomp(bcpow($g, $n->value), $this->value) == -1) {
|
||||
$g = bcmul($g, "2");
|
||||
}
|
||||
// if (g^n==num) num is a power of 2, we're lucky, end of job
|
||||
if (bccomp(bcpow($g, $n->value), $this->value) == 0) {
|
||||
$root->value = $g;
|
||||
break;
|
||||
}
|
||||
|
||||
// if we're here num wasn't a power of 2 :(
|
||||
$og = $g; // og means original guess and here is our upper bound
|
||||
$g = bcdiv($g, "2"); // g is set to be our lower bound
|
||||
$step = bcdiv(bcsub($og, $g), "2"); // step is the half of upper bound - lower bound
|
||||
$g = bcadd($g, $step); // we start at lower bound + step , basically in the middle of our interval
|
||||
|
||||
// while step!=1
|
||||
|
||||
while (bccomp($step, "1")==1) {
|
||||
$guess = bcpow($g, $n);
|
||||
$step=bcdiv($step,"2");
|
||||
$comp=bccomp($guess,$this->value); // compare our guess with real number
|
||||
if ($comp==-1) { // if guess is lower we add the new step
|
||||
$g=bcadd($g,$step);
|
||||
} else if ($comp==1) { // if guess is higher we sub the new step
|
||||
$g=bcsub($g,$step);
|
||||
} else { // if guess is exactly the num we're done, we return the value
|
||||
$root->value = $g;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// whatever happened, g is the closest guess we can make so return it
|
||||
$root->value = $g;
|
||||
break;
|
||||
default:
|
||||
// g is our guess number
|
||||
$g = $two;
|
||||
// while (g^n < num) g=g*2
|
||||
while ($g->pow($n)->compare($this) == -1) {
|
||||
$g = $g->multiply($two);
|
||||
}
|
||||
// if (g^n==num) num is a power of 2, we're lucky, end of job
|
||||
// == 0 bccomp(bcpow($g,$n), $n->value)==0
|
||||
if ($g->pow($n)->equals($this)) {
|
||||
$root = $g;
|
||||
break;
|
||||
}
|
||||
|
||||
// if we're here num wasn't a power of 2 :(
|
||||
$og = $g; // og means original guess and here is our upper bound
|
||||
$g = $g->divide($two)[0]; // g is set to be our lower bound
|
||||
$step = $og->subtract($g)->divide($two)[0]; // step is the half of upper bound - lower bound
|
||||
$g = $g->add($step); // we start at lower bound + step , basically in the middle of our interval
|
||||
|
||||
// while step!=1
|
||||
|
||||
while ($step->compare($one) == 1) {
|
||||
$guess = $g->pow($n);
|
||||
$step = $step->divide($two)[0];
|
||||
$comp = $guess->compare($this); // compare our guess with real number
|
||||
if ($comp == -1) { // if guess is lower we add the new step
|
||||
$g = $g->add($step);
|
||||
} else if ($comp == 1) { // if guess is higher we sub the new step
|
||||
$g = $g->subtract($step);
|
||||
} else { // if guess is exactly the num we're done, we return the value
|
||||
$root = $g;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// whatever happened, g is the closest guess we can make so return it
|
||||
$root = $g;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return $this->_normalize($root);
|
||||
}
|
||||
/**
|
||||
* Performs exponentiation.
|
||||
*
|
||||
*
|
||||
* @param \phpseclib\Math\BigInteger $n
|
||||
* @return \phpseclib\Math\BigInteger
|
||||
* @access public
|
||||
*/
|
||||
function pow($n)
|
||||
{
|
||||
$zero = new static(0);
|
||||
if ($n->compare($zero) == 0) return new static(1); // n^0 = 1
|
||||
$isnegative = $n->is_negative; // n^-e = 1 / n^e
|
||||
if ($isnegative == true) {
|
||||
$n->is_negative = false;
|
||||
}
|
||||
$res = new static();
|
||||
switch (MATH_BIGINTEGER_MODE) {
|
||||
case self::MODE_GMP:
|
||||
$res->value = gmp_pow($this->value, $n->value);
|
||||
if($isnegative) {
|
||||
$res->value = gmp_div_q('1', $res->value);
|
||||
}
|
||||
return $res;
|
||||
case self::MODE_BCMATH:
|
||||
$res->value = bcpow($this->value, $n->value);
|
||||
if($isnegative) {
|
||||
$res->value = bcdiv('1', $res->value);
|
||||
}
|
||||
return $res;
|
||||
default:
|
||||
$one = new static(1);
|
||||
$res = $this;
|
||||
while (!$n->equals($one)) {
|
||||
$res = $res->multiply($this);
|
||||
$n = $n->subtract($one);
|
||||
}
|
||||
if($isnegative) {
|
||||
$res->value = $one->divide($res);
|
||||
}
|
||||
return $res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Divides a BigInteger by a regular integer
|
||||
*
|
||||
@ -1794,6 +1953,8 @@ class BigInteger
|
||||
return $this->modPow($e, $n);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Sliding Window k-ary Modular Exponentiation
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user