This commit is contained in:
danogentili 2016-07-18 18:43:50 +02:00
parent b808531197
commit fced0ddc0f
4 changed files with 149 additions and 198 deletions

View File

@ -174,6 +174,7 @@ class Session
$this->MAX_RETRY = 5; $this->MAX_RETRY = 5;
$this->AUTH_MAX_RETRY = 5; $this->AUTH_MAX_RETRY = 5;
$this->struct = new \danog\PHP\Struct(); $this->struct = new \danog\PHP\Struct();
$this->PrimeModule = new PrimeModule();
try { try {
$this->tl = new TL('https://core.telegram.org/schema/mtproto-json'); $this->tl = new TL('https://core.telegram.org/schema/mtproto-json');
} catch (Exception $e) { } catch (Exception $e) {
@ -273,7 +274,8 @@ 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 = bytes_to_long($pq_bytes); $pq = bytes_to_long($pq_bytes);
list($p, $q) = primefactors($pq); var_dump($this->PrimeModule->primefactors($pq));
list($p, $q) = $this->PrimeModule->primefactors($pq);
if ($p > $q) { if ($p > $q) {
list($p, $q) = [$q, $p]; list($p, $q) = [$q, $p];
} }
@ -310,7 +312,7 @@ class Session
pyjslib_printnl(sprintf('Server-client time delta = %.1f s', $this->timedelta)); pyjslib_printnl(sprintf('Server-client time delta = %.1f s', $this->timedelta));
$dh_prime = new bytes_to_long($dh_prime_str); $dh_prime = new bytes_to_long($dh_prime_str);
$g_a = new bytes_to_long($g_a_str); $g_a = new bytes_to_long($g_a_str);
assert(prime::isprime($dh_prime)); assert($this->PrimeModule->isprime($dh_prime));
$retry_id = 0; $retry_id = 0;
$b_str = random_bytes(256); $b_str = random_bytes(256);
$b = new bytes_to_long($b_str); $b = new bytes_to_long($b_str);

View File

@ -145,8 +145,9 @@ 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']
vis(pq_bytes)
pq = bytes_to_long(pq_bytes) pq = bytes_to_long(pq_bytes)
print(prime.primefactors(2118588165281151121))
exit()
[p, q] = prime.primefactors(pq) [p, q] = prime.primefactors(pq)
if p > q: (p, q) = (q, p) if p > q: (p, q) = (q, p)
assert p*q == pq and p < q assert p*q == pq and p < q

335
prime.php
View File

@ -2,228 +2,177 @@
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php'); set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__).DIRECTORY_SEPARATOR.'libpy2php');
require_once 'libpy2php.php'; require_once 'libpy2php.php';
function everynth($array, $n) class PrimeModule {
{ function __construct() {
$result = []; $this->smallprimeset = array_unique($this->primesbelow(100000));
$i = -1; $this->_smallprimeset = 100000;
foreach ($array as $key => $value) { $this->smallprimes = $this->primesbelow(10000);
if ($i++ == $n) { }
$i = 0; function primesbelow($N) {
} $res = [];
if ($i == 0) { for ($i = 2; $i <= $N; $i++)
$result[$key] = $value; {
if($i % 2 != 1) continue;
$d = 3;
$x = sqrt($i);
while ($i % $d != 0 && $d < $x) $d += 2;
if((($i % $d == 0 && $i != $d) * 1) == 0) $res[] = $i;
} }
return $res;
} }
return $result; function isprime($n, $precision = 7)
} {
function array_merge_ignore_keys($array1, $array2) if (($n == 1) || (($n % 2) == 0)) {
{ return false;
if (count($array1) == count($array2)) { } elseif (($n < 1)) {
$i = -1; throw new Exception('Out of bounds, first argument must be > 0');
foreach ($array1 as $key => $val) { } elseif (($n < $this->_smallprimeset)) {
$array1[$key] = $array2[$i++]; return in_array($n, $this->smallprimeset);
} }
} else { $d = ($n - 1);
return; $s = 0;
} while (($d % 2) == 0) {
$d = floor($d / 2);
return $array1; $s += 1;
} }
function primesbelow($N) foreach (pyjslib_range($precision) as $repeat) {
{ $a = rand(2, ($n - 2));
$correction = (($N % 6) > 1); $x = posmod(pow($a, $d), $n);
$N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1)][($N % 6)]; if (($x == 1) || ($x == ($n - 1))) {
$sieve = array_fill(0, floor($N / 3), true); continue;
$sieve[0] = false;
foreach (pyjslib_range(floor((int)(pow($N, 0.5)) / 3) + 1) as $i) {
if ($sieve[$i]) {
$k = ((3 * $i) + 1) | 1;
foreach (pyjslib_range(floor(($k*$k) / 3), 2*$k) as $key) {
} }
array_fill(0, floor((floor($N / 6) - floor(($k * $k) / 6) - 1) / $k) + 1, false) foreach (pyjslib_range(($s - 1)) as $r) {
$sieve = array_merge( $x = posmod(pow($x, 2), $n);
$sieve, array_merge( if (($x == 1)) {
everynth( return false;
array_splice( }
$sieve, floor( if (($x == ($n - 1))) {
( break;
$k * $k + 4 * $k - 2 * $k * ($i % 2) }
) / 3
)
), 2 * $k
),
(
)
)
);
}
}
var_dump($sieve);
return [2, 3] + array_map(function ($i, $sieve) {
if ($sieve[$i]) {
return (3 * $i + 1) | 1;
}
}, pyjslib_range(1, (($N / 3) - $correction)), $sieve);
}
$smallprimeset = array_unique(primesbelow(100000));
$_smallprimeset = 100000;
function isprime($n, $precision = 7)
{
if (($n == 1) || (($n % 2) == 0)) {
return false;
} elseif (($n < 1)) {
throw new $ValueError('Out of bounds, first argument must be > 0');
} elseif (($n < $_smallprimeset)) {
return in_array($n, $smallprimeset);
}
$d = ($n - 1);
$s = 0;
while ((($d % 2) == 0)) {
$d = floor($d / 2);
$s += 1;
}
foreach (pyjslib_range($precision) as $repeat) {
$a = random::randrange(2, ($n - 2));
$x = pow($a, $d, $n);
if (($x == 1) || ($x == ($n - 1))) {
continue;
}
foreach (pyjslib_range(($s - 1)) as $r) {
$x = pow($x, 2, $n);
if (($x == 1)) {
return false;
}
if (($x == ($n - 1))) {
break;
} }
} }
}
return true; return true;
}
function pollard_brent($n)
{
if ((($n % 2) == 0)) {
return 2;
} }
if ((($n % 3) == 0)) { function pollard_brent($n)
return 3; {
} if ((($n % 2) == 0)) {
list($y, $c, $m) = [random::randint(1, ($n - 1)), random::randint(1, ($n - 1)), random::randint(1, ($n - 1))]; return 2;
list($g, $r, $q) = [1, 1, 1];
while (($g == 1)) {
$x = $y;
foreach (pyjslib_range($r) as $i) {
$y = ((pow($y, 2, $n) + $c) % $n);
} }
$k = 0; if ((($n % 3) == 0)) {
while (($k < $r) && ($g == 1)) { return 3;
$ys = $y; }
foreach (pyjslib_range(min($m, ($r - $k))) as $i) { list($y, $c, $m) = [rand(1, ($n - 1)), rand(1, ($n - 1)), rand(1, ($n - 1))];
list($g, $r, $q) = [1, 1, 1];
while (($g == 1)) {
$x = $y;
foreach (pyjslib_range($r) as $i) {
$y = ((pow($y, 2, $n) + $c) % $n); $y = ((pow($y, 2, $n) + $c) % $n);
$q = (($q * abs(($x - $y))) % $n);
} }
$g = gcd($q, $n); $k = 0;
$k += $m; while (($k < $r) && ($g == 1)) {
$ys = $y;
foreach (pyjslib_range(min($m, ($r - $k))) as $i) {
$y = ((pow($y, 2, $n) + $c) % $n);
$q = (($q * abs(($x - $y))) % $n);
}
$g = gcd($q, $n);
$k += $m;
}
$r *= 2;
} }
$r *= 2; if (($g == $n)) {
} while (true) {
if (($g == $n)) { $ys = ((pow($ys, 2, $n) + $c) % $n);
while (true) { $g = gcd(abs(($x - $ys)), $n);
$ys = ((pow($ys, 2, $n) + $c) % $n); if (($g > 1)) {
$g = gcd(abs(($x - $ys)), $n); break;
if (($g > 1)) { }
break;
} }
} }
}
return $g; return $g;
} }
$smallprimes = primesbelow(10000); function primefactors($n, $sort = false)
function primefactors($n, $sort = false) {
{ $factors = [];
global $smallprimes; $limit = ((int)(pow($n, 0.5)) + 1);
$factors = []; foreach ($this->smallprimes as $checker) {
$limit = (pyjslib_int(pow($n, 0.5)) + 1);
foreach ($smallprimes as $checker) {
if (($checker > $limit)) {
break;
}
while ((($n % $checker) == 0)) {
$factors[] = $checker;
$n = floor($n / $checker);
$limit = (pyjslib_int(pow($n, 0.5)) + 1);
if (($checker > $limit)) { if (($checker > $limit)) {
break; break;
} }
while (($n % $checker) == 0) {
$factors[] = $checker;
$n = floor($n / $checker);
$limit = ((int)(pow($n, 0.5)) + 1);
if (($checker > $limit)) {
break;
}
}
} }
} if (($n < 2)) {
if (($n < 2)) { return $factors;
}
while (($n > 1)) {
if ($this->isprime($n)) {
$factors[] = $n;
break;
}
$factor = $this->pollard_brent($n);
$factors[] = $this->primefactors($factor);
$n = floor($n / $factor);
}
if ($sort) {
$factors = sort($factors);
}
return $factors; return $factors;
} }
while (($n > 1)) { function factorization($n)
if (isprime($n)) { {
$factors[] = $n; $factors = [];
break; foreach (primefactors($n) as $p1) {
if(isset($factors[$p1])) {
$factors[$p1] += 1;
} else {
$factors[$p1] = 1;
}
} }
$factor = pollard_brent($n);
$factors->extend(primefactors($factor));
$n = floor($n / $factor);
}
if ($sort) {
$factors->sort();
}
return $factors; return $factors;
} }
function factorization($n) function totient($n)
{ {
$factors = []; $totients = [];
foreach (primefactors($n) as $p1) { if (($n == 0)) {
try { return 1;
$factors[$p1] += 1;
} catch (KeyError $e) {
$factors[$p1] = 1;
} }
} if(isset($totients[$n])) {
return $totients[$n];
}
$tot = 1;
foreach (factorization($n) as $p => $exp) {
$tot *= (($p - 1) * pow($p, ($exp - 1)));
}
$totients[$n] = $tot;
return $factors; return $tot;
}
$totients = [];
function totient($n)
{
if (($n == 0)) {
return 1;
} }
try { function gcd($a, $b)
return $totients[$n]; {
} catch (KeyError $e) { if (($a == $b)) {
} return $a;
$tot = 1; }
foreach (factorization($n)->items() as list($p, $exp)) { while (($b > 0)) {
$tot *= (($p - 1) * pow($p, ($exp - 1))); list($a, $b) = [$b, ($a % $b)];
} }
$totients[$n] = $tot;
return $tot;
}
function gcd($a, $b)
{
if (($a == $b)) {
return $a; return $a;
} }
while (($b > 0)) { function lcm($a, $b)
list($a, $b) = [$b, ($a % $b)]; {
return floor(abs(($a * $b)) / gcd($a, $b));
} }
return $a; }
}
function lcm($a, $b)
{
return floor(abs(($a * $b)) / gcd($a, $b));
}

View File

@ -14,7 +14,6 @@ def primesbelow(N):
k = (3 * i + 1) | 1 k = (3 * i + 1) | 1
sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1) sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1) sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
exit()
return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]] return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]
smallprimeset = set(primesbelow(100000)) smallprimeset = set(primesbelow(100000))
@ -94,11 +93,11 @@ def primefactors(n, sort=False):
if checker > limit: break if checker > limit: break
if n < 2: return factors if n < 2: return factors
while n > 1: while n > 1:
if isprime(n): if isprime(n):
factors.append(n) factors.append(n)
break break
print(pollard_brent(n))
factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
n //= factor n //= factor