Finally fixed authorization

This commit is contained in:
Daniil Gentili 2016-08-15 02:37:59 +02:00
parent 2bc5dc62b7
commit f99f432056
5 changed files with 21 additions and 20 deletions

View File

@ -13,8 +13,6 @@ Here all of the things that still have to be done in this library.
You can (and you are also encouraged to) contribute by completing any of the following points. You can (and you are also encouraged to) contribute by completing any of the following points.
The importance of each item will range from 1 to 5. It's better to start from the most important items. The importance of each item will range from 1 to 5. It's better to start from the most important items.
* In Session.php, complete the function that creates the authorization key (5).
* In Crypto.php or aes256.php, choose which of the ige implementation to use and complete it (4).
* In Session.php and TL, manage rpc errors, notifications, error codes and basically everything that isn't a normal response (4). * In Session.php and TL, manage rpc errors, notifications, error codes and basically everything that isn't a normal response (4).
* In Connection.php and Session.php, add support for http, https and (maybe) udp connections and fix tcp intermediate connections (3). * In Connection.php and Session.php, add support for http, https and (maybe) udp connections and fix tcp intermediate connections (3).
* In API.php, complete a decent authorization flow that supports both bots and normal users (2). * In API.php, complete a decent authorization flow that supports both bots and normal users (2).

View File

@ -21,8 +21,8 @@ class API extends Exception
set_error_handler([$this, 'ExceptionErrorHandler']); set_error_handler([$this, 'ExceptionErrorHandler']);
$this->session = new Session($params); $this->session = new Session($params);
$this->session->create_auth_key(); $this->session->create_auth_key();
$future_salts = $this->session->method_call('get_future_salts', 3); $future_salts = $this->get_future_salts(3);
Logging::log($future_salts, 3); $this->session->log->log($future_salts);
} }
public function __destruct() public function __destruct()
@ -33,6 +33,6 @@ class API extends Exception
public function __call($name, $arguments) public function __call($name, $arguments)
{ {
return $session->method_call($name, $arguments); return $this->session->method_call($name, $arguments);
} }
} }

View File

@ -44,6 +44,7 @@ class Crypt
} }
$cipher = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_ECB); $cipher = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_ECB);
$cipher->setKey($key); $cipher->setKey($key);
$cipher->paddable = false;
$blocksize = $cipher->block_size; $blocksize = $cipher->block_size;
if ((strlen($message) % $blocksize) != 0) { if ((strlen($message) % $blocksize) != 0) {
throw new Exception('message must be a multiple of 16 bytes (try adding '.(16 - (strlen($message) % 16)).' bytes of padding)'); throw new Exception('message must be a multiple of 16 bytes (try adding '.(16 - (strlen($message) % 16)).' bytes of padding)');

View File

@ -61,6 +61,9 @@ class Logging
$mode = $this->mode; $mode = $this->mode;
} }
foreach ($params as $param) { foreach ($params as $param) {
if (!is_string($param)) {
$param = var_export($param, true);
}
switch ($mode) { switch ($mode) {
case '1': case '1':
error_log($param); error_log($param);

View File

@ -108,7 +108,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
$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 = \phpseclib\Crypt\Random::string(posmod(-strlen($encrypted_data), 16)); $padding = \phpseclib\Crypt\Random::string(Tools::posmod(-strlen($encrypted_data), 16));
$this->log->log(strlen($encrypted_data.$padding)); $this->log->log(strlen($encrypted_data.$padding));
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);
@ -306,7 +306,6 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
$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);
$answer_with_hash = Crypt::ige_decrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv); $answer_with_hash = Crypt::ige_decrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv);
var_dump($answer_with_hash);
$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 = $this->tl->deserialize(Tools::fopen_and_write('php://memory', 'rw+b', $answer)); $server_DH_inner_data = $this->tl->deserialize(Tools::fopen_and_write('php://memory', 'rw+b', $answer));
@ -317,29 +316,29 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
throw new Exception('Handshake: wrong 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 = new \phpseclib\Math\BigInteger($server_DH_inner_data['g']);
$g_a_str = $server_DH_inner_data['g_a']; $g_a_str = $server_DH_inner_data['g_a'];
$server_time = $server_DH_inner_data['server_time']; $server_time = $server_DH_inner_data['server_time'];
$this->timedelta = ($server_time - time()); $this->timedelta = ($server_time - time());
$this->log->log(sprintf('Server-client time delta = %.1f s', $this->timedelta)); $this->log->log(sprintf('Server-client time delta = %.1f s', $this->timedelta));
$dh_prime = $this->struct->unpack('>Q', $dh_prime_str); $dh_prime = new \phpseclib\Math\BigInteger($dh_prime_str, 256);
$g_a = $this->struct->unpack('>Q', $g_a_str); $g_a = new \phpseclib\Math\BigInteger($g_a_str, 256);
if (!$this->PrimeModule->isprime($dh_prime)) { if (!$dh_prime->isPrime()) {
throw new Exception("Handshake: dh_prime isn't a 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 = new \phpseclib\Math\BigInteger($b_str, 256);
$g_b = pow($g, $b, $dh_prime); $g_b = $g->powMod($b, $dh_prime);
$g_b_str = $this->struct->pack('>Q', $g_b); $g_b_str = $g_b->toBytes();
$data = serialize_obj(['client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str]); $data = $this->tl->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.\phpseclib\Crypt\Random::string(posmod(-strlen($data_with_sha), 16)); $data_with_sha_padded = $data_with_sha.\phpseclib\Crypt\Random::string(Tools::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 (Tools::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]);
$auth_key = pow($g_a, $b, $dh_prime); $auth_key = $g_a->powMod($b, $dh_prime);
$auth_key_str = $this->struct->pack('>Q', $auth_key); $auth_key_str = $auth_key->toBytes();
$auth_key_sha = sha1($auth_key_str, true); $auth_key_sha = sha1($auth_key_str, true);
$auth_key_aux_hash = substr($auth_key_sha, 0, 8); $auth_key_aux_hash = substr($auth_key_sha, 0, 8);
$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);
@ -356,7 +355,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
throw new Exception('Handshake: wrong new_nonce_hash1'); throw new Exception('Handshake: wrong new_nonce_hash1');
} }
$this->log->log('Diffie Hellman key exchange processed successfully'); $this->log->log('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 = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0);
$this->auth_key = $auth_key_str; $this->auth_key = $auth_key_str;
$this->auth_key_id = substr($auth_key_sha, -8); $this->auth_key_id = substr($auth_key_sha, -8);
$this->log->log('Auth key generated'); $this->log->log('Auth key generated');