Switched from assertions to exceptions
This commit is contained in:
parent
6acaae877a
commit
bcf0d6d012
16
TL.php
16
TL.php
@ -107,17 +107,17 @@ class TL
|
|||||||
{
|
{
|
||||||
switch ($type_) {
|
switch ($type_) {
|
||||||
case 'int':
|
case 'int':
|
||||||
assert(is_numeric($value));
|
if(!is_numeric($value)) throw new Exception("serialize_param: given value isn't numeric");
|
||||||
assert(strlen(decbin($value)) <= 32);
|
if(!(strlen(decbin($value)) <= 32)) throw new Exception("Given value is too long.");
|
||||||
fwrite($bytes_io, $this->struct->pack('<i', $value));
|
fwrite($bytes_io, $this->struct->pack('<i', $value));
|
||||||
break;
|
break;
|
||||||
case 'long':
|
case 'long':
|
||||||
assert(is_numeric($value));
|
if(!is_numeric($value)) throw new Exception("serialize_param: given value isn't numeric");
|
||||||
fwrite($bytes_io, $this->struct->pack('<q', $value));
|
fwrite($bytes_io, $this->struct->pack('<q', $value));
|
||||||
break;
|
break;
|
||||||
case 'int128':
|
case 'int128':
|
||||||
case 'int256':
|
case 'int256':
|
||||||
assert(is_string($value));
|
if(!is_string($value)) throw new Exception("serialize_param: given value isn't a string");
|
||||||
fwrite($bytes_io, $value);
|
fwrite($bytes_io, $value);
|
||||||
break;
|
break;
|
||||||
case 'string':
|
case 'string':
|
||||||
@ -144,7 +144,7 @@ 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');
|
if(!(get_resource_type($bytes_io) == 'file' || get_resource_type($bytes_io) == 'stream')) throw new Exception("An invalid bytes_io handle provided.");
|
||||||
switch ($type_) {
|
switch ($type_) {
|
||||||
case 'int':
|
case 'int':
|
||||||
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
|
$x = $this->struct->unpack('<i', fread($bytes_io, 4)) [0];
|
||||||
@ -167,7 +167,7 @@ class TL
|
|||||||
case 'string':
|
case 'string':
|
||||||
case 'bytes':
|
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);
|
if($l > 254) throw new Exception("Length is too big");;
|
||||||
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);
|
||||||
@ -176,10 +176,10 @@ class TL
|
|||||||
$x = fread($bytes_io, $l);
|
$x = fread($bytes_io, $l);
|
||||||
fread($bytes_io, posmod(-($l + 1), 4));
|
fread($bytes_io, posmod(-($l + 1), 4));
|
||||||
}
|
}
|
||||||
assert(is_string($x));
|
if(!is_string($x)) throw new Exception("deserialize: generated value isn't a string");
|
||||||
break;
|
break;
|
||||||
case 'vector':
|
case 'vector':
|
||||||
assert($subtype != null);
|
if($subtype == null) throw new Exception("deserialize: subtype isn't 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) {
|
||||||
|
46
mtproto.php
46
mtproto.php
@ -1,5 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
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';
|
||||||
require_once 'os_path.php';
|
require_once 'os_path.php';
|
||||||
@ -196,8 +195,8 @@ class Session
|
|||||||
$encrypted_data = substr($packet, 28, -4 - 28);
|
$encrypted_data = substr($packet, 28, -4 - 28);
|
||||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, 'from server');
|
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, 'from server');
|
||||||
$decrypted_data = crypt::ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
$decrypted_data = crypt::ige_decrypt($encrypted_data, $aes_key, $aes_iv);
|
||||||
assert((substr($decrypted_data, 0, 8 - 0) == $this->server_salt));
|
if (substr($decrypted_data, 0, 8) != $this->server_salt) throw new Exception("Server salt does not match.");
|
||||||
assert((substr($decrypted_data, 8, 16 - 8) == $this->session_id));
|
if (substr($decrypted_data, 8, 8) != $this->session_id) throw new Exception("Session id does not match.");
|
||||||
$message_id = substr($decrypted_data, 16, 24 - 16);
|
$message_id = substr($decrypted_data, 16, 24 - 16);
|
||||||
$seq_no = $this->struct->unpack('<I', substr($decrypted_data, 24, 28 - 24)) [0];
|
$seq_no = $this->struct->unpack('<I', substr($decrypted_data, 24, 28 - 24)) [0];
|
||||||
$message_data_length = $this->struct->unpack('<I', substr($decrypted_data, 28, 32 - 28)) [0];
|
$message_data_length = $this->struct->unpack('<I', substr($decrypted_data, 28, 32 - 28)) [0];
|
||||||
@ -220,9 +219,13 @@ class Session
|
|||||||
echo 'An error occurred while calling method '.$method.': '.$e->getMessage().PHP_EOL.'Stack trace:'.$e->getTraceAsString().PHP_EOL.'Retrying to call method...'.PHP_EOL.PHP_EOL;
|
echo 'An error occurred while calling method '.$method.': '.$e->getMessage().PHP_EOL.'Stack trace:'.$e->getTraceAsString().PHP_EOL.'Retrying to call method...'.PHP_EOL.PHP_EOL;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if ($server_answer == null) {
|
||||||
|
throw new Exception("An error occurred while calling method ".$method.'.');
|
||||||
|
}
|
||||||
return $this->tl->deserialize(fopen_and_write('php://memory', 'rw+b', $server_answer));
|
return $this->tl->deserialize(fopen_and_write('php://memory', 'rw+b', $server_answer));
|
||||||
}
|
}
|
||||||
|
throw new Exception("An error occurred while calling method ".$method.'.');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create_auth_key()
|
public function create_auth_key()
|
||||||
@ -230,6 +233,9 @@ class Session
|
|||||||
$nonce = \phpseclib\Crypt\Random::string(16);
|
$nonce = \phpseclib\Crypt\Random::string(16);
|
||||||
pyjslib_printnl('Requesting pq');
|
pyjslib_printnl('Requesting pq');
|
||||||
$ResPQ = $this->method_call('req_pq', ['nonce' => $nonce]);
|
$ResPQ = $this->method_call('req_pq', ['nonce' => $nonce]);
|
||||||
|
if ($ResPQ['nonce'] !== $nonce) {
|
||||||
|
throw new Exception("Handshake: wrong nonce");
|
||||||
|
}
|
||||||
$server_nonce = $ResPQ['server_nonce'];
|
$server_nonce = $ResPQ['server_nonce'];
|
||||||
$public_key_fingerprint = (int) $ResPQ['server_public_key_fingerprints'][0];
|
$public_key_fingerprint = (int) $ResPQ['server_public_key_fingerprints'][0];
|
||||||
$pq_bytes = $ResPQ['pq'];
|
$pq_bytes = $ResPQ['pq'];
|
||||||
@ -241,23 +247,23 @@ class Session
|
|||||||
if ($p->compare($q) > 0) {
|
if ($p->compare($q) > 0) {
|
||||||
list($p, $q) = [$q, $p];
|
list($p, $q) = [$q, $p];
|
||||||
}
|
}
|
||||||
assert(($pq->equals($p->multiply($q))) && ($p < $q));
|
if(!(($pq->equals($p->multiply($q))) && ($p < $q))) throw new Exception("Handshake: couldn't compute p or q.");
|
||||||
pyjslib_printnl(sprintf('Factorization %s = %s * %s', $pq, $p, $q));
|
pyjslib_printnl(sprintf('Factorization %s = %s * %s', $pq, $p, $q));
|
||||||
$p_bytes = $this->struct->pack('>I', (string) $p);
|
$p_bytes = $this->struct->pack('>Q', (string) $p);
|
||||||
$q_bytes = $this->struct->pack('>I', (string) $q);
|
$q_bytes = $this->struct->pack('>Q', (string) $q);
|
||||||
$f = file_get_contents(__DIR__.'/rsa.pub');
|
$f = file_get_contents(__DIR__.'/rsa.pub');
|
||||||
$key = new \phpseclib\Crypt\RSA();
|
$key = new \phpseclib\Crypt\RSA();
|
||||||
$key->load($f);
|
$key->load($f);
|
||||||
$new_nonce = \phpseclib\Crypt\Random::string(32);
|
$new_nonce = \phpseclib\Crypt\Random::string(32);
|
||||||
$data = $this->tl->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 = $this->tl->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]);
|
||||||
$sha_digest = sha1($data, true);
|
$sha_digest = sha1($data, true);
|
||||||
$random_bytes = \phpseclib\Crypt\Random::string(((255 - strlen($data)) - strlen($sha_digest)));
|
$random_bytes = \phpseclib\Crypt\Random::string(255 - strlen($data) - strlen($sha_digest));
|
||||||
$to_encrypt = $sha_digest.$data.$random_bytes;
|
$to_encrypt = $sha_digest.$data.$random_bytes;
|
||||||
$encrypted_data = $key->_raw_encrypt($to_encrypt);
|
$encrypted_data = $key->_raw_encrypt($to_encrypt);
|
||||||
pyjslib_printnl('Starting Diffie Hellman key exchange');
|
pyjslib_printnl('Starting Diffie Hellman key exchange');
|
||||||
$server_dh_params = $this->method_call('req_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'p' => $p_bytes, 'q' => $q_bytes, 'public_key_fingerprint' => $public_key_fingerprint, 'encrypted_data' => $encrypted_data]);
|
$server_dh_params = $this->method_call('req_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'p' => $p_bytes, 'q' => $q_bytes, 'public_key_fingerprint' => $public_key_fingerprint, 'encrypted_data' => $encrypted_data]);
|
||||||
assert($nonce == $server_dh_params['nonce']);
|
if($nonce != $server_dh_params['nonce']) throw new Exception("Handshake: wrong nonce.");
|
||||||
assert($server_nonce == $server_dh_params['server_nonce']);
|
if($server_nonce != $server_dh_params['server_nonce']) throw new Exception("Handshake: wrong server nonce.");
|
||||||
$encrypted_answer = $server_dh_params['encrypted_answer'];
|
$encrypted_answer = $server_dh_params['encrypted_answer'];
|
||||||
$tmp_aes_key = sha1($new_nonce.$server_nonce, true).substr(sha1($server_nonce.$new_nonce, true), 0, 12);
|
$tmp_aes_key = sha1($new_nonce.$server_nonce, true).substr(sha1($server_nonce.$new_nonce, true), 0, 12);
|
||||||
$tmp_aes_iv = substr(sha1($server_nonce.$new_nonce, true), 12, 8).sha1($new_nonce.$new_nonce, true).substr($new_nonce, 0, 4);
|
$tmp_aes_iv = substr(sha1($server_nonce.$new_nonce, true), 12, 8).sha1($new_nonce.$new_nonce, true).substr($new_nonce, 0, 4);
|
||||||
@ -265,8 +271,8 @@ class Session
|
|||||||
$answer_hash = substr($answer_with_hash, 0, 20);
|
$answer_hash = substr($answer_with_hash, 0, 20);
|
||||||
$answer = substr($answer_with_hash, 20);
|
$answer = substr($answer_with_hash, 20);
|
||||||
$server_DH_inner_data = deserialize(fopen_and_write('php://memory', 'rw+b', $answer));
|
$server_DH_inner_data = deserialize(fopen_and_write('php://memory', 'rw+b', $answer));
|
||||||
assert($nonce == $server_DH_inner_data['nonce']);
|
if($nonce != $server_DH_inner_data['nonce']) throw new Exception("Handshake: wrong nonce");
|
||||||
assert($server_nonce == $server_DH_inner_data['server_nonce']);
|
if($server_nonce != $server_DH_inner_data['server_nonce']) throw new Exception("Handshake: wrong server nonce");;
|
||||||
$dh_prime_str = $server_DH_inner_data['dh_prime'];
|
$dh_prime_str = $server_DH_inner_data['dh_prime'];
|
||||||
$g = $server_DH_inner_data['g'];
|
$g = $server_DH_inner_data['g'];
|
||||||
$g_a_str = $server_DH_inner_data['g_a'];
|
$g_a_str = $server_DH_inner_data['g_a'];
|
||||||
@ -275,7 +281,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 = $this->struct->unpack('>Q', $dh_prime_str);
|
$dh_prime = $this->struct->unpack('>Q', $dh_prime_str);
|
||||||
$g_a = $this->struct->unpack('>Q', $g_a_str);
|
$g_a = $this->struct->unpack('>Q', $g_a_str);
|
||||||
assert($this->PrimeModule->isprime($dh_prime));
|
if(!$this->PrimeModule->isprime($dh_prime)) throw new Exception("Handshake: dh_prime isn't a prime.");;
|
||||||
$retry_id = 0;
|
$retry_id = 0;
|
||||||
$b_str = \phpseclib\Crypt\Random::string(256);
|
$b_str = \phpseclib\Crypt\Random::string(256);
|
||||||
$b = $this->struct->unpack('>Q', $b_str);
|
$b = $this->struct->unpack('>Q', $b_str);
|
||||||
@ -294,10 +300,10 @@ class Session
|
|||||||
$new_nonce_hash1 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
$new_nonce_hash1 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
||||||
$new_nonce_hash2 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
$new_nonce_hash2 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
||||||
$new_nonce_hash3 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
$new_nonce_hash3 = substr(sha1($new_nonce.''.$auth_key_aux_hash, true), -16);
|
||||||
assert($Set_client_DH_params_answer['nonce'] == $nonce);
|
if($Set_client_DH_params_answer['nonce'] != $nonce) throw new Exception("Handshake: wrong nonce.");
|
||||||
assert($Set_client_DH_params_answer['server_nonce'] == $server_nonce);
|
if($Set_client_DH_params_answer['server_nonce'] != $server_nonce) throw new Exception("Handshake: wrong server nonce");;
|
||||||
if ($Set_client_DH_params_answer->name == 'dh_gen_ok') {
|
if ($Set_client_DH_params_answer->name == 'dh_gen_ok') {
|
||||||
assert($Set_client_DH_params_answer['new_nonce_hash1'] == $new_nonce_hash1);
|
if($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) throw new Exception("Handshake: wrong new_nonce_hash1");;
|
||||||
pyjslib_printnl('Diffie Hellman key exchange processed successfully');
|
pyjslib_printnl('Diffie Hellman key exchange processed successfully');
|
||||||
$this->server_salt = new strxor(substr($new_nonce, 0, 8 - 0), substr($server_nonce, 0, 8 - 0));
|
$this->server_salt = new strxor(substr($new_nonce, 0, 8 - 0), substr($server_nonce, 0, 8 - 0));
|
||||||
$this->auth_key = $auth_key_str;
|
$this->auth_key = $auth_key_str;
|
||||||
@ -305,11 +311,11 @@ class Session
|
|||||||
pyjslib_printnl('Auth key generated');
|
pyjslib_printnl('Auth key generated');
|
||||||
|
|
||||||
return 'Auth Ok';
|
return 'Auth Ok';
|
||||||
} elseif (($Set_client_DH_params_answer->name == 'dh_gen_retry')) {
|
} elseif ($Set_client_DH_params_answer->name == 'dh_gen_retry') {
|
||||||
assert($Set_client_DH_params_answer['new_nonce_hash2'] == $new_nonce_hash2);
|
if($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) throw new Exception("Handshake: wrong new_nonce_hash_2");
|
||||||
pyjslib_printnl('Retry Auth');
|
pyjslib_printnl('Retry Auth');
|
||||||
} elseif (($Set_client_DH_params_answer->name == 'dh_gen_fail')) {
|
} elseif ($Set_client_DH_params_answer->name == 'dh_gen_fail') {
|
||||||
assert($Set_client_DH_params_answer['new_nonce_hash3'] == $new_nonce_hash3);
|
if($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) throw new Exception("Handshake: wrong new_nonce_hash_3");
|
||||||
pyjslib_printnl('Auth Failed');
|
pyjslib_printnl('Auth Failed');
|
||||||
throw new Exception('Auth Failed');
|
throw new Exception('Auth Failed');
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user