Fixed serialization/deserialization, now fixing mess in prime number generation module...

This commit is contained in:
danogentili 2016-07-18 17:11:37 +02:00
parent 423f83ef7d
commit b3bfacea85
10 changed files with 77193 additions and 147 deletions

2
.vscode/launch.json vendored
View File

@ -5,7 +5,7 @@
"name": "Listen for XDebug", "name": "Listen for XDebug",
"type": "php", "type": "php",
"request": "launch", "request": "launch",
"port": 9000 "port": 9002
}, },
{ {
"name": "Launch currently open script", "name": "Launch currently open script",

5
Caddyfile Normal file
View File

@ -0,0 +1,5 @@
localhost:80 {
fastcgi / 127.0.0.1:9001 {
index index.php
}
}

59
TL.php
View File

@ -105,28 +105,37 @@ class TL
public function serialize_param($bytes_io, $type_, $value) public function serialize_param($bytes_io, $type_, $value)
{ {
if (($type_ == 'int')) { switch ($type_) {
assert(is_numeric($value)); case 'int':
assert(is_int($value));
assert(strlen(decbin($value)) <= 32); assert(strlen(decbin($value)) <= 32);
fwrite($bytes_io, $this->struct->pack('<i', $value)); fwrite($bytes_io, $this->struct->pack('<i', $value));
} elseif (($type_ == 'long')) { break;
assert(is_numeric($value)); case 'long':
assert(is_long($value));
fwrite($bytes_io, $this->struct->pack('<q', $value)); fwrite($bytes_io, $this->struct->pack('<q', $value));
} elseif (in_array($type_, ['int128', 'int256'])) { break;
case 'int128':
case 'int256':
assert(is_string($value)); assert(is_string($value));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
} elseif ($type_ == 'string' || $type_ == 'bytes') { break;
case 'string':
case 'bytes':
$l = len($value); $l = len($value);
if (($l < 254)) { if (($l < 254)) {
fwrite($bytes_io, $this->struct->pack('<b', $l)); fwrite($bytes_io, $this->struct->pack('<b', $l));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.((-$l - 1) % 4))); fwrite($bytes_io, pack('@'.posmod((-$l - 1), 4)));
} else { } else {
fwrite($bytes_io, string2bin('\xfe')); fwrite($bytes_io, string2bin('\xfe'));
fwrite($bytes_io, substr($this->struct->pack('<i', $l), 0, 3)); fwrite($bytes_io, substr($this->struct->pack('<i', $l), 0, 3));
fwrite($bytes_io, $value); fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.(-$l % 4))); fwrite($bytes_io, pack('@'.posmod(-$l, 4)));
} }
break;
default:
break;
} }
} }
@ -136,44 +145,53 @@ class TL
public function deserialize($bytes_io, $type_ = null, $subtype = null) public function deserialize($bytes_io, $type_ = null, $subtype = null)
{ {
assert(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream'); assert(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream');
if (($type_ == 'int')) { switch ($type_) {
case 'int':
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0]; $x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
} elseif (($type_ == '#')) { break;
case '#':
$x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0]; $x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0];
} elseif (($type_ == 'long')) { break;
case 'long':
$x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0]; $x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0];
} elseif (($type_ == 'double')) { break;
case 'double':
$x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0]; $x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0];
} elseif (($type_ == 'int128')) { break;
case 'int128':
$x = fread($bytes_io, 16); $x = fread($bytes_io, 16);
} elseif (($type_ == 'int256')) { break;
case 'int256':
$x = fread($bytes_io, 32); $x = fread($bytes_io, 32);
} elseif (($type_ == 'string') || ($type_ == 'bytes')) { break;
case 'string':
case 'bytes':
$l = $this->struct->unpack('<B', fread($bytes_io, 1)) [0]; $l = $this->struct->unpack('<B', fread($bytes_io, 1)) [0];
assert($l <= 254); assert($l <= 254);
if (($l == 254)) { if (($l == 254)) {
$long_len = $this->struct->unpack('<I', fread($bytes_io, 3).string2bin('\x00')) [0]; $long_len = $this->struct->unpack('<I', fread($bytes_io, 3).string2bin('\x00')) [0];
$x = fread($bytes_io, $long_len); $x = fread($bytes_io, $long_len);
fread($bytes_io, (-$long_len % 4)); fread($bytes_io, posmod(-$long_len, 4));
} else { } else {
$x = fread($bytes_io, $l); $x = fread($bytes_io, $l);
fread($bytes_io, (($l + 1) % 4)); fread($bytes_io, posmod(-($l + 1), 4));
} }
assert(is_string($x)); assert(is_string($x));
} elseif (($type_ == 'vector')) { break;
case 'vector':
assert($subtype != null); assert($subtype != null);
$count = $this->struct->unpack('<l', fread($bytes_io, 4)) [0]; $count = $this->struct->unpack('<l', fread($bytes_io, 4)) [0];
$x = []; $x = [];
foreach (pyjslib_range($count) as $i) { foreach (pyjslib_range($count) as $i) {
$x[] = $this->deserialize($bytes_io, $subtype); $x[] = $this->deserialize($bytes_io, $subtype);
} }
} else { break;
default:
if (isset($this->constructor_type[$type_])) { if (isset($this->constructor_type[$type_])) {
$tl_elem = $this->constructor_type[$type_]; $tl_elem = $this->constructor_type[$type_];
} else { } else {
$Idata = fread($bytes_io, 4); $Idata = fread($bytes_io, 4);
$i = $this->struct->unpack('<i', $Idata) [0]; $i = $this->struct->unpack('<i', $Idata) [0];
var_dump(ftell($bytes_io));
if (isset($this->constructor_id[$i])) { if (isset($this->constructor_id[$i])) {
$tl_elem = $this->constructor_id[$i]; $tl_elem = $this->constructor_id[$i];
} else { } else {
@ -190,6 +208,7 @@ class TL
$x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']); $x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']);
} }
} }
break;
} }
return $x; return $x;

1
TL.py
View File

@ -152,7 +152,6 @@ def deserialize(bytes_io, type_=None, subtype=None):
# Boxed types # Boxed types
Idata = bytes_io.read(4) Idata = bytes_io.read(4)
i = struct.unpack('<i', Idata)[0] # read type ID i = struct.unpack('<i', Idata)[0] # read type ID
print(hexlify(bytes_io.getvalue()))
try: try:
tl_elem = tl.constructor_id[i] tl_elem = tl.constructor_id[i]
except KeyError: except KeyError:

View File

@ -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();
/** /**
* Function to get hex crc32 * Function to get hex crc32
* :param data: Data to encode. * :param data: Data to encode.
@ -27,7 +27,7 @@ function hex_dump(...$what)
var_dump(bin2hex($w)); var_dump(bin2hex($w));
} }
} }
/** /**
* len. * len.
* *
* Get the length of a string or of an array * Get the length of a string or of an array
@ -36,14 +36,13 @@ function hex_dump(...$what)
* *
* @return int with the length * @return int with the length
**/ **/
function len($input) function len($input)
{ {
if (is_array($input)) { if (is_array($input)) {
return count($input); return count($input);
} }
return strlen($input); return strlen($input);
} }
/** /**
* Function to visualize byte streams. Split into bytes, print to console. * Function to visualize byte streams. Split into bytes, print to console.
@ -62,7 +61,7 @@ function vis($bs)
}, array_slice($bs, $i * $symbols_in_one_line, ($i + 1) * $symbols_in_one_line)) }, array_slice($bs, $i * $symbols_in_one_line, ($i + 1) * $symbols_in_one_line))
).PHP_EOL; ).PHP_EOL;
} }
if (!(len($bs) % $symbols_in_one_line == 0)) { if (len($bs) % $symbols_in_one_line != 0) {
echo($i + 1) * $symbols_in_one_line.' | '.implode(' ', echo($i + 1) * $symbols_in_one_line.' | '.implode(' ',
array_map(function ($el) { array_map(function ($el) {
return bin2hex($el); return bin2hex($el);
@ -71,24 +70,13 @@ function vis($bs)
} }
} }
/** /**
* bytes_to_long(string) : long * posmod(numeric,numeric) : numeric
* Convert a byte string to a long integer. * Works just like the % (modulus) operator, only returns always a postive number
* This is (essentially) the inverse of long_to_bytes().
*/ */
function bytes_to_long($s) function posmod($a, $b) {
{ $resto = $a % $b;
$acc = 0; if($resto < 0) $resto += abs($b);
$length = strlen($s); return $resto;
if (($length % 4)) {
$extra = (4 - ($length % 4));
$s = (($b('') * $extra) + $s);
$length = ($length + $extra);
}
foreach (pyjslib_range(0, $length, 4) as $i) {
$acc = ($acc << 32 + $this->struct->unpack('I', array_slice($s, $i, ($i + 4) - $i))[0]);
}
return $acc;
} }
function fread_all($handle) function fread_all($handle)
@ -117,29 +105,49 @@ function fopen_and_write($filename, $mode, $data)
*/ */
function long_to_bytes($n, $blocksize = 0) function long_to_bytes($n, $blocksize = 0)
{ {
$s = $b(''); $s = null;
$n = long($n); $n = long($n);
while (($n > 0)) { while (($n > 0)) {
$s = ($this->struct->pack('I', $n & 4294967295) + $s); $s = $GLOBALS["struct"]->pack('I', $n & 4294967295) . $s;
$n = $n >> 32; $n = $n >> 32;
} }
foreach (pyjslib_range(strlen($s)) as $i) { foreach (pyjslib_range(strlen($s)) as $i) {
if (($s[$i] != $b('')[0])) { if (($s[$i] != string2bin('\000')[0])) {
break; break;
} }
} }
$s = array_slice($s, $i); $s = substr($s, $i);
if (($blocksize > 0) && (strlen($s) % $blocksize)) { if ($blocksize > 0 && strlen($s) % $blocksize) {
$s = ((($blocksize - (strlen($s) % $blocksize)) * $b('')) + $s); $s = pack("@" . $blocksize - (strlen($s) % $blocksize)) . $s;
} }
return $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)
{
//return $GLOBALS["struct"]->unpack('>Q', $s)[0];
$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;
foreach (explode('\\', $string) as $s) { foreach (explode('\\', $string) as $s) {
if ($s != null && $s[0] == 'x') { if ($s != null && strlen($s) == 3) {
$res .= hex2bin(substr($s, 1)); $res .= hex2bin(substr($s, 1));
} }
} }
@ -192,7 +200,7 @@ class Session
$encrypted_data = $encrypted_data =
$this->server_salt.$this->session_id.$message_id.$this->struct->pack('<II', $this->number, strlen($message_data)).$message_data; $this->server_salt.$this->session_id.$message_id.$this->struct->pack('<II', $this->number, strlen($message_data)).$message_data;
$message_key = substr(sha1($encrypted_data, true), -16); $message_key = substr(sha1($encrypted_data, true), -16);
$padding = random_bytes((-strlen($encrypted_data) % 16)); $padding = random_bytes(posmod(-strlen($encrypted_data), 16));
echo strlen($encrypted_data.$padding).PHP_EOL; echo strlen($encrypted_data.$padding).PHP_EOL;
list($aes_key, $aes_iv) = $this->aes_calculate($message_key); list($aes_key, $aes_iv) = $this->aes_calculate($message_key);
$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);
@ -266,7 +274,7 @@ class Session
$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); list($p, $q) = primefactors($pq);
if (($p > $q)) { if ($p > $q) {
list($p, $q) = [$q, $p]; list($p, $q) = [$q, $p];
} }
assert((($p * $q) == $pq) && ($p < $q)); assert((($p * $q) == $pq) && ($p < $q));
@ -310,7 +318,7 @@ class Session
$g_b_str = new long_to_bytes($g_b); $g_b_str = new long_to_bytes($g_b);
$data = py2php_kwargs_function_call('serialize_obj', ['client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str]); $data = py2php_kwargs_function_call('serialize_obj', ['client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str]);
$data_with_sha = (sha1($data, true) + $data); $data_with_sha = (sha1($data, true) + $data);
$data_with_sha_padded = ($data_with_sha + random_bytes((-strlen($data_with_sha) % 16))); $data_with_sha_padded = ($data_with_sha + random_bytes(posmod(-strlen($data_with_sha), 16)));
$encrypted_data = crypt::ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv); $encrypted_data = crypt::ige_encrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
foreach (pyjslib_range(1, $this->AUTH_MAX_RETRY) as $i) { foreach (pyjslib_range(1, $this->AUTH_MAX_RETRY) as $i) {
$Set_client_DH_params_answer = $this->method_call('set_client_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'encrypted_data' => $encrypted_data]); $Set_client_DH_params_answer = $this->method_call('set_client_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'encrypted_data' => $encrypted_data]);

View File

@ -80,7 +80,6 @@ class Session:
message_data) message_data)
message_key = SHA.new(encrypted_data).digest()[-16:] message_key = SHA.new(encrypted_data).digest()[-16:]
padding = os.urandom((-len(encrypted_data)) % 16) padding = os.urandom((-len(encrypted_data)) % 16)
print(len(encrypted_data+padding))
aes_key, aes_iv = self.aes_calculate(message_key) aes_key, aes_iv = self.aes_calculate(message_key)
message = (self.auth_key_id + message_key + message = (self.auth_key_id + message_key +
@ -109,7 +108,6 @@ class Session:
if auth_key_id == b'\x00\x00\x00\x00\x00\x00\x00\x00': if auth_key_id == b'\x00\x00\x00\x00\x00\x00\x00\x00':
# No encryption - Plain text # No encryption - Plain text
(message_id, message_length) = struct.unpack("<8sI", packet[12:24]) (message_id, message_length) = struct.unpack("<8sI", packet[12:24])
print(len(packet[12:24]))
data = packet[24:24+message_length] data = packet[24:24+message_length]
elif auth_key_id == self.auth_key_id: elif auth_key_id == self.auth_key_id:
message_key = packet[12:28] message_key = packet[12:28]
@ -143,13 +141,12 @@ class Session:
ResPQ = self.method_call('req_pq', nonce=nonce) ResPQ = self.method_call('req_pq', nonce=nonce)
server_nonce = ResPQ['server_nonce'] server_nonce = ResPQ['server_nonce']
exit()
# TODO: selecting RSA public key based on this fingerprint # TODO: selecting RSA public key based on this fingerprint
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)
[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

View File

@ -36,9 +36,13 @@ function primesbelow($N)
$N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1)][($N % 6)]; $N = [0 => $N, 1 => ($N - 1), 2 => ($N + 4), 3 => ($N + 3), 4 => ($N + 2), 5 => ($N + 1)][($N % 6)];
$sieve = array_fill(0, floor($N / 3), true); $sieve = array_fill(0, floor($N / 3), true);
$sieve[0] = false; $sieve[0] = false;
foreach (pyjslib_range((floor(pyjslib_int(pow($N, 0.5)) / 3) + 1)) as $i) { foreach (pyjslib_range(floor((int)(pow($N, 0.5)) / 3) + 1) as $i) {
if ($sieve[$i]) { if ($sieve[$i]) {
$k = ((3 * $i) + 1) | 1; $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)
$sieve = array_merge( $sieve = array_merge(
$sieve, array_merge( $sieve, array_merge(
everynth( everynth(
@ -51,34 +55,13 @@ function primesbelow($N)
), 2 * $k ), 2 * $k
), ),
( (
array_fill(
0,
(
floor(
(
(
floor(
$N / 6
) - floor(
(
(
($k * $k) + (4 * $k)
) - (
(2 * $k) * ($i % 2)
)
) / 6
)
) - 1
) / $k
) + 1
),
false
)
) )
) )
); );
} }
} }
var_dump($sieve);
return [2, 3] + array_map(function ($i, $sieve) { return [2, 3] + array_map(function ($i, $sieve) {
if ($sieve[$i]) { if ($sieve[$i]) {

View File

@ -14,6 +14,7 @@ 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))

View File

@ -5,7 +5,7 @@ require_once 'libpy2php.php';
require_once 'os.php'; require_once 'os.php';
require_once 'mtproto.php'; require_once 'mtproto.php';
$config = parse_ini_file('credentials', true); $config = parse_ini_file('credentials', true);
if (!($config)) { if (!$config) {
pyjslib_printnl('File \'credentials\' seems to not exist.'); pyjslib_printnl('File \'credentials\' seems to not exist.');
$exit(-1); $exit(-1);
} }

77034
trace.txt Normal file

File diff suppressed because it is too large Load Diff