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",
"type": "php",
"request": "launch",
"port": 9000
"port": 9002
},
{
"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
}
}

161
TL.php
View File

@ -105,28 +105,37 @@ class TL
public function serialize_param($bytes_io, $type_, $value)
{
if (($type_ == 'int')) {
assert(is_numeric($value));
assert(strlen(decbin($value)) <= 32);
fwrite($bytes_io, $this->struct->pack('<i', $value));
} elseif (($type_ == 'long')) {
assert(is_numeric($value));
fwrite($bytes_io, $this->struct->pack('<q', $value));
} elseif (in_array($type_, ['int128', 'int256'])) {
assert(is_string($value));
fwrite($bytes_io, $value);
} elseif ($type_ == 'string' || $type_ == 'bytes') {
$l = len($value);
if (($l < 254)) {
fwrite($bytes_io, $this->struct->pack('<b', $l));
switch ($type_) {
case 'int':
assert(is_int($value));
assert(strlen(decbin($value)) <= 32);
fwrite($bytes_io, $this->struct->pack('<i', $value));
break;
case 'long':
assert(is_long($value));
fwrite($bytes_io, $this->struct->pack('<q', $value));
break;
case 'int128':
case 'int256':
assert(is_string($value));
fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.((-$l - 1) % 4)));
} else {
fwrite($bytes_io, string2bin('\xfe'));
fwrite($bytes_io, substr($this->struct->pack('<i', $l), 0, 3));
fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.(-$l % 4)));
}
break;
case 'string':
case 'bytes':
$l = len($value);
if (($l < 254)) {
fwrite($bytes_io, $this->struct->pack('<b', $l));
fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.posmod((-$l - 1), 4)));
} else {
fwrite($bytes_io, string2bin('\xfe'));
fwrite($bytes_io, substr($this->struct->pack('<i', $l), 0, 3));
fwrite($bytes_io, $value);
fwrite($bytes_io, pack('@'.posmod(-$l, 4)));
}
break;
default:
break;
}
}
@ -136,60 +145,70 @@ class TL
public function deserialize($bytes_io, $type_ = null, $subtype = null)
{
assert(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream');
if (($type_ == 'int')) {
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
} elseif (($type_ == '#')) {
$x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0];
} elseif (($type_ == 'long')) {
$x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0];
} elseif (($type_ == 'double')) {
$x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0];
} elseif (($type_ == 'int128')) {
$x = fread($bytes_io, 16);
} elseif (($type_ == 'int256')) {
$x = fread($bytes_io, 32);
} elseif (($type_ == 'string') || ($type_ == 'bytes')) {
$l = $this->struct->unpack('<B', fread($bytes_io, 1)) [0];
assert($l <= 254);
if (($l == 254)) {
$long_len = $this->struct->unpack('<I', fread($bytes_io, 3).string2bin('\x00')) [0];
$x = fread($bytes_io, $long_len);
fread($bytes_io, (-$long_len % 4));
} else {
$x = fread($bytes_io, $l);
fread($bytes_io, (($l + 1) % 4));
}
assert(is_string($x));
} elseif (($type_ == 'vector')) {
assert($subtype != null);
$count = $this->struct->unpack('<l', fread($bytes_io, 4)) [0];
$x = [];
foreach (pyjslib_range($count) as $i) {
$x[] = $this->deserialize($bytes_io, $subtype);
}
} else {
if (isset($this->constructor_type[$type_])) {
$tl_elem = $this->constructor_type[$type_];
} else {
$Idata = fread($bytes_io, 4);
$i = $this->struct->unpack('<i', $Idata) [0];
var_dump(ftell($bytes_io));
if (isset($this->constructor_id[$i])) {
$tl_elem = $this->constructor_id[$i];
switch ($type_) {
case 'int':
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
break;
case '#':
$x = $this->struct->unpack('<I', fread($bytes_io, 4)) [0];
break;
case 'long':
$x = $this->struct->unpack('<q', fread($bytes_io, 8)) [0];
break;
case 'double':
$x = $this->struct->unpack('<d', fread($bytes_io, 8)) [0];
break;
case 'int128':
$x = fread($bytes_io, 16);
break;
case 'int256':
$x = fread($bytes_io, 32);
break;
case 'string':
case 'bytes':
$l = $this->struct->unpack('<B', fread($bytes_io, 1)) [0];
assert($l <= 254);
if (($l == 254)) {
$long_len = $this->struct->unpack('<I', fread($bytes_io, 3).string2bin('\x00')) [0];
$x = fread($bytes_io, $long_len);
fread($bytes_io, posmod(-$long_len, 4));
} else {
throw new Exception(sprintf('Could not extract type: %s', $type_));
$x = fread($bytes_io, $l);
fread($bytes_io, posmod(-($l + 1), 4));
}
assert(is_string($x));
break;
case 'vector':
assert($subtype != null);
$count = $this->struct->unpack('<l', fread($bytes_io, 4)) [0];
$x = [];
foreach (pyjslib_range($count) as $i) {
$x[] = $this->deserialize($bytes_io, $subtype);
}
break;
default:
if (isset($this->constructor_type[$type_])) {
$tl_elem = $this->constructor_type[$type_];
} else {
$Idata = fread($bytes_io, 4);
$i = $this->struct->unpack('<i', $Idata) [0];
if (isset($this->constructor_id[$i])) {
$tl_elem = $this->constructor_id[$i];
} else {
throw new Exception(sprintf('Could not extract type: %s', $type_));
}
}
}
$base_boxed_types = ['Vector t', 'Int', 'Long', 'Double', 'String', 'Int128', 'Int256'];
if (in_array($tl_elem->type, $base_boxed_types)) {
$x = $this->deserialize($bytes_io, $tl_elem->predicate, $subtype);
} else {
$x = new TLObject($tl_elem);
foreach ($tl_elem->params as $arg) {
$x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']);
$base_boxed_types = ['Vector t', 'Int', 'Long', 'Double', 'String', 'Int128', 'Int256'];
if (in_array($tl_elem->type, $base_boxed_types)) {
$x = $this->deserialize($bytes_io, $tl_elem->predicate, $subtype);
} else {
$x = new TLObject($tl_elem);
foreach ($tl_elem->params as $arg) {
$x[$arg['name']] = $this->deserialize($bytes_io, $arg['type'], $arg['subtype']);
}
}
}
break;
}
return $x;

1
TL.py
View File

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

View File

@ -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();
/**
* Function to get hex crc32
* :param data: Data to encode.
@ -27,23 +27,22 @@ function hex_dump(...$what)
var_dump(bin2hex($w));
}
}
/**
* len.
*
* Get the length of a string or of an array
*
* @param $input String or array to parse
*
* @return int with the length
**/
function len($input)
{
if (is_array($input)) {
return count($input);
}
return strlen($input);
/**
* len.
*
* Get the length of a string or of an array
*
* @param $input String or array to parse
*
* @return int with the length
**/
function len($input)
{
if (is_array($input)) {
return count($input);
}
return strlen($input);
}
/**
* 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))
).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(' ',
array_map(function ($el) {
return bin2hex($el);
@ -71,24 +70,13 @@ function vis($bs)
}
}
/**
* bytes_to_long(string) : long
* Convert a byte string to a long integer.
* This is (essentially) the inverse of long_to_bytes().
* posmod(numeric,numeric) : numeric
* Works just like the % (modulus) operator, only returns always a postive number
*/
function bytes_to_long($s)
{
$acc = 0;
$length = strlen($s);
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 posmod($a, $b) {
$resto = $a % $b;
if($resto < 0) $resto += abs($b);
return $resto;
}
function fread_all($handle)
@ -117,29 +105,49 @@ function fopen_and_write($filename, $mode, $data)
*/
function long_to_bytes($n, $blocksize = 0)
{
$s = $b('');
$s = null;
$n = long($n);
while (($n > 0)) {
$s = ($this->struct->pack('I', $n & 4294967295) + $s);
$s = $GLOBALS["struct"]->pack('I', $n & 4294967295) . $s;
$n = $n >> 32;
}
foreach (pyjslib_range(strlen($s)) as $i) {
if (($s[$i] != $b('')[0])) {
if (($s[$i] != string2bin('\000')[0])) {
break;
}
}
$s = array_slice($s, $i);
if (($blocksize > 0) && (strlen($s) % $blocksize)) {
$s = ((($blocksize - (strlen($s) % $blocksize)) * $b('')) + $s);
$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)
{
//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)
{
$res = null;
foreach (explode('\\', $string) as $s) {
if ($s != null && $s[0] == 'x') {
if ($s != null && strlen($s) == 3) {
$res .= hex2bin(substr($s, 1));
}
}
@ -192,7 +200,7 @@ class Session
$encrypted_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);
$padding = random_bytes((-strlen($encrypted_data) % 16));
$padding = random_bytes(posmod(-strlen($encrypted_data), 16));
echo strlen($encrypted_data.$padding).PHP_EOL;
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);
@ -266,7 +274,7 @@ class Session
$pq_bytes = $ResPQ['pq'];
$pq = bytes_to_long($pq_bytes);
list($p, $q) = primefactors($pq);
if (($p > $q)) {
if ($p > $q) {
list($p, $q) = [$q, $p];
}
assert((($p * $q) == $pq) && ($p < $q));
@ -310,7 +318,7 @@ class Session
$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_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);
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]);

View File

@ -80,7 +80,6 @@ class Session:
message_data)
message_key = SHA.new(encrypted_data).digest()[-16:]
padding = os.urandom((-len(encrypted_data)) % 16)
print(len(encrypted_data+padding))
aes_key, aes_iv = self.aes_calculate(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':
# No encryption - Plain text
(message_id, message_length) = struct.unpack("<8sI", packet[12:24])
print(len(packet[12:24]))
data = packet[24:24+message_length]
elif auth_key_id == self.auth_key_id:
message_key = packet[12:28]
@ -143,13 +141,12 @@ class Session:
ResPQ = self.method_call('req_pq', nonce=nonce)
server_nonce = ResPQ['server_nonce']
exit()
# TODO: selecting RSA public key based on this fingerprint
public_key_fingerprint = ResPQ['server_public_key_fingerprints'][0]
pq_bytes = ResPQ['pq']
vis(pq_bytes)
pq = bytes_to_long(pq_bytes)
[p, q] = prime.primefactors(pq)
if p > q: (p, q) = (q, p)
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)];
$sieve = array_fill(0, floor($N / 3), true);
$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]) {
$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(
everynth(
@ -51,34 +55,13 @@ function primesbelow($N)
), 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) {
if ($sieve[$i]) {

View File

@ -14,6 +14,7 @@ def primesbelow(N):
k = (3 * i + 1) | 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)
exit()
return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]
smallprimeset = set(primesbelow(100000))

View File

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

77034
trace.txt Normal file

File diff suppressed because it is too large Load Diff