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_id[$z->id] = $z;
|
||||||
$this->method_name[$z->method] = $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)
|
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 'prime.php';
|
||||||
require_once 'TL.php';
|
require_once 'TL.php';
|
||||||
require_once 'vendor/autoload.php';
|
require_once 'vendor/autoload.php';
|
||||||
$struct = new \danog\PHP\Struct();
|
$struct = new \danog\PHP\StructClass();
|
||||||
/**
|
/**
|
||||||
* Function to get hex crc32
|
* Function to get hex crc32
|
||||||
* :param data: Data to encode.
|
* :param data: Data to encode.
|
||||||
@ -101,59 +101,6 @@ function fopen_and_write($filename, $mode, $data)
|
|||||||
|
|
||||||
return $handle;
|
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)
|
function string2bin($string)
|
||||||
{
|
{
|
||||||
$res = null;
|
$res = null;
|
||||||
@ -204,8 +151,7 @@ class Session
|
|||||||
*/
|
*/
|
||||||
public function send_message($message_data)
|
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)) {
|
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;
|
$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);
|
$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;
|
$step1 = $this->struct->pack('<II', (strlen($message) + 12), $this->number).$message;
|
||||||
var_dump(newcrc32($step1));
|
|
||||||
$step2 = $step1.$this->struct->pack('<I', newcrc32($step1));
|
$step2 = $step1.$this->struct->pack('<I', newcrc32($step1));
|
||||||
fwrite($this->sock, $step2);
|
fwrite($this->sock, $step2);
|
||||||
$this->number += 1;
|
$this->number += 1;
|
||||||
@ -266,7 +211,6 @@ class Session
|
|||||||
{
|
{
|
||||||
foreach (range(1, $this->MAX_RETRY) as $i) {
|
foreach (range(1, $this->MAX_RETRY) as $i) {
|
||||||
try {
|
try {
|
||||||
//var_dump(py2php_kwargs_function_call('serialize_method', [$method], $kwargs));
|
|
||||||
$this->send_message($this->tl->serialize_method($method, $kwargs));
|
$this->send_message($this->tl->serialize_method($method, $kwargs));
|
||||||
$server_answer = $this->recv_message();
|
$server_answer = $this->recv_message();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
@ -287,7 +231,6 @@ class Session
|
|||||||
$public_key_fingerprint = $ResPQ['server_public_key_fingerprints'][0];
|
$public_key_fingerprint = $ResPQ['server_public_key_fingerprints'][0];
|
||||||
$pq_bytes = $ResPQ['pq'];
|
$pq_bytes = $ResPQ['pq'];
|
||||||
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
|
$pq = new \phpseclib\Math\BigInteger($pq_bytes, 256);
|
||||||
|
|
||||||
var_dump($this->PrimeModule->primefactors($pq));
|
var_dump($this->PrimeModule->primefactors($pq));
|
||||||
die;
|
die;
|
||||||
var_dump($this->PrimeModule->pollard_brent(15));
|
var_dump($this->PrimeModule->pollard_brent(15));
|
||||||
@ -300,9 +243,9 @@ class Session
|
|||||||
}
|
}
|
||||||
assert((($p * $q) == $pq) && ($p < $q));
|
assert((($p * $q) == $pq) && ($p < $q));
|
||||||
pyjslib_printnl(sprintf('Factorization %d = %d * %d', [$pq, $p, $q]));
|
pyjslib_printnl(sprintf('Factorization %d = %d * %d', [$pq, $p, $q]));
|
||||||
$p_bytes = long_to_bytes($p);
|
$p_bytes = $this->struct->pack('>Q', $p);
|
||||||
$q_bytes = long_to_bytes($q);
|
$q_bytes = $this->struct->pack('>Q', $q);
|
||||||
$f = pyjslib_open(__DIR__.'/rsa.pub');
|
$f = file_get_contents(__DIR__.'/rsa.pub');
|
||||||
$key = RSA::importKey($f->read());
|
$key = RSA::importKey($f->read());
|
||||||
$new_nonce = random_bytes(32);
|
$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]);
|
$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)
|
public function primefactors($n, $sort = false)
|
||||||
{
|
{
|
||||||
$factors = [];
|
$factors = [];
|
||||||
if ($n->compare(PHP_INT_MAX) === -1) {
|
$limit = $n->root()->add(1);
|
||||||
var_dump((int) $n->toString());
|
|
||||||
}
|
|
||||||
$limit = ((int) (pow($n, 0.5)) + 1);
|
|
||||||
foreach ($this->smallprimes as $checker) {
|
foreach ($this->smallprimes as $checker) {
|
||||||
if (($checker > $limit)) {
|
if (($limit < $checker)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (($n % $checker) == 0) {
|
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));
|
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
|
* Divides a BigInteger by a regular integer
|
||||||
*
|
*
|
||||||
@ -1794,6 +1953,8 @@ class BigInteger
|
|||||||
return $this->modPow($e, $n);
|
return $this->modPow($e, $n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sliding Window k-ary Modular Exponentiation
|
* Sliding Window k-ary Modular Exponentiation
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user