Fixed serialization/deserialization, now fixing mess in prime number generation module...
This commit is contained in:
parent
423f83ef7d
commit
b3bfacea85
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -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
5
Caddyfile
Normal file
@ -0,0 +1,5 @@
|
||||
localhost:80 {
|
||||
fastcgi / 127.0.0.1:9001 {
|
||||
index index.php
|
||||
}
|
||||
}
|
161
TL.php
161
TL.php
@ -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
1
TL.py
@ -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:
|
||||
|
98
mtproto.php
98
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();
|
||||
/**
|
||||
* 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]);
|
||||
|
@ -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
|
||||
|
31
prime.php
31
prime.php
@ -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]) {
|
||||
|
1
prime.py
1
prime.py
@ -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))
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user