Secret chat fixes
This commit is contained in:
parent
77923b231d
commit
85b71b2a3e
@ -22,7 +22,6 @@ try {
|
||||
} catch (\danog\MadelineProto\Exception $e) {
|
||||
var_dump($e->getMessage());
|
||||
}
|
||||
var_dump(file_exists('.env'));
|
||||
if (file_exists('.env')) {
|
||||
echo 'Loading .env...'.PHP_EOL;
|
||||
$dotenv = new Dotenv\Dotenv(getcwd());
|
||||
@ -74,17 +73,19 @@ echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $Madel
|
||||
|
||||
$offset = 0;
|
||||
while (true) {
|
||||
$updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
|
||||
//\danog\MadelineProto\Logger::log([$updates]);
|
||||
foreach ($updates as $update) {
|
||||
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
|
||||
switch ($update['update']['_']) {
|
||||
case 'updateNewEncryptedMessage':
|
||||
$i = 0;
|
||||
while (true) {
|
||||
$MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => $i++]]);
|
||||
}
|
||||
try {
|
||||
$updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout
|
||||
//\danog\MadelineProto\Logger::log([$updates]);
|
||||
foreach ($updates as $update) {
|
||||
$offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id
|
||||
switch ($update['update']['_']) {
|
||||
case 'updateNewEncryptedMessage':
|
||||
$i = 0;
|
||||
while (true) {
|
||||
$MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => $i++]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\danog\MadelineProto\SecurityException $e) { ; }
|
||||
echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('bot.madeline', $MadelineProto).' bytes'.PHP_EOL;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ trait UpdateHandler
|
||||
$this->set_update_state($difference['state']);
|
||||
//var_dump($difference['new_encrypted_messages']);
|
||||
foreach ($difference['new_encrypted_messages'] as $encrypted) {
|
||||
$this->handle_encrypted_update(['_' => 'updateNewEncryptedMessage', 'message' => $encrypted]);
|
||||
$this->handle_encrypted_update(['_' => 'updateNewEncryptedMessage', 'message' => $encrypted], true);
|
||||
}
|
||||
$this->handle_multiple_update($difference['other_updates']);
|
||||
$this->handle_update_messages($difference['new_messages']);
|
||||
|
@ -24,6 +24,12 @@ trait AuthKeyHandler
|
||||
|
||||
public function accept_secret_chat($params)
|
||||
{
|
||||
if ($this->secret_chat_status($params['id']) !== 0) {
|
||||
//var_dump($this->secret_chat_status($params['id']));
|
||||
\danog\MadelineProto\Logger::log(["I've already accepted secret chat ".$params['id']]);
|
||||
|
||||
return false;
|
||||
}
|
||||
$this->should_serialize = true;
|
||||
$dh_config = $this->get_dh_config();
|
||||
\danog\MadelineProto\Logger::log(['Generating b...'], \danog\MadelineProto\Logger::VERBOSE);
|
||||
@ -85,9 +91,8 @@ trait AuthKeyHandler
|
||||
unset($this->temp_requested_secret_chats[$params['id']]);
|
||||
$key['fingerprint'] = substr(sha1($key['auth_key'], true), -8);
|
||||
//var_dump($key);
|
||||
|
||||
if ($key['fingerprint'] !== $params['key_fingerprint']) {
|
||||
$this->method_call('messages.discardEncryption', ['chat_id' => $params['id']], ['datacenter' => $this->datacenter->curdc]);
|
||||
$this->discard_secret_chat($params['id']);
|
||||
throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
|
||||
}
|
||||
$key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16);
|
||||
@ -232,4 +237,22 @@ trait AuthKeyHandler
|
||||
{
|
||||
return $this->secret_chats[$chat];
|
||||
}
|
||||
|
||||
public function discard_secret_chat($chat) {
|
||||
if (isset($this->secret_chats[$chat])) {
|
||||
unset($this->secret_chats[$chat]);
|
||||
}
|
||||
if (isset($this->temp_requested_secret_chats[$chat])) {
|
||||
unset($this->temp_requested_secret_chats[$chat]);
|
||||
}
|
||||
if (isset($this->temp_rekeyed_secret_chats[$chat])) {
|
||||
unset($this->temp_rekeyed_secret_chats[$chat]);
|
||||
}
|
||||
try {
|
||||
$this->method_call('messages.discardEncryption', ['chat_id' => $chat], ['datacenter' => $this->datacenter->curdc]);
|
||||
} catch (\danog\MadelineProto\RPCErrorException $e) {
|
||||
if ($e->rpc !== "ENCRYPTION_ALREADY_DECLINED") throw $e;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,9 @@ trait MessageHandler
|
||||
if (($this->secret_chats[$chat_id]['ttr'] <= 0 || time() - $this->secret_chats[$chat_id]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$chat_id]['rekeying'][0] === 0) {
|
||||
$this->rekey($chat_id);
|
||||
}
|
||||
if ($this->secret_chats[$chat_id]['layer'] !== 8) {
|
||||
if ($this->secret_chats[$chat_id]['layer'] > 8) {
|
||||
$message = ['_' => 'decryptedMessageLayer', 'layer' => $this->secret_chats[$chat_id]['layer'], 'in_seq_no' => $this->generate_secret_in_seq_no($chat_id), 'out_seq_no' => $this->generate_secret_out_seq_no($chat_id), 'message' => $message];
|
||||
$this->secret_chats[$chat_id]['out_seq_no']++;
|
||||
}
|
||||
$this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message;
|
||||
$message = $this->serialize_object(['type' => $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer'], $message, $this->secret_chats[$chat_id]['layer']);
|
||||
@ -40,14 +41,13 @@ trait MessageHandler
|
||||
list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], 'to server');
|
||||
|
||||
$message .= $this->random($this->posmod(-strlen($message), 16));
|
||||
$this->secret_chats[$chat_id]['out_seq_no']++;
|
||||
|
||||
$message = $this->secret_chats[$chat_id]['key']['fingerprint'].$message_key.$this->ige_encrypt($message, $aes_key, $aes_iv);
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
public function handle_encrypted_update($message)
|
||||
public function handle_encrypted_update($message, $test = false)
|
||||
{
|
||||
if (!isset($this->secret_chats[$message['message']['chat_id']])) {
|
||||
\danog\MadelineProto\Logger::log('I do not have the secret chat '.$message['message']['chat_id'].' in the database, skipping message...');
|
||||
@ -60,10 +60,12 @@ trait MessageHandler
|
||||
//var_dump($auth_key_id, $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']);
|
||||
if (isset($this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint'])) {
|
||||
if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint']) {
|
||||
$this->discard_secret_chat($message['message']['chat_id']);
|
||||
throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch');
|
||||
}
|
||||
$old = true;
|
||||
} else {
|
||||
$this->discard_secret_chat($message['message']['chat_id']);
|
||||
throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch');
|
||||
}
|
||||
}
|
||||
@ -94,7 +96,11 @@ trait MessageHandler
|
||||
}
|
||||
unset($message['message']['bytes']);
|
||||
$message['message']['decrypted_message'] = $deserialized;
|
||||
$this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']++] = $message['message'];
|
||||
if ($test) {
|
||||
var_dump($message);
|
||||
}
|
||||
$this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']] = $message['message'];
|
||||
|
||||
//var_dump($message);
|
||||
$this->handle_decrypted_update($message);
|
||||
}
|
||||
|
@ -72,6 +72,13 @@ trait ResponseHandler
|
||||
break;
|
||||
case 'decryptedMessageLayer':
|
||||
if ($this->check_secret_out_seq_no($update['message']['chat_id'], $update['message']['decrypted_message']['out_seq_no']) && $this->check_secret_in_seq_no($update['message']['chat_id'], $update['message']['decrypted_message']['in_seq_no'])) {
|
||||
$this->secret_chats[$update['message']['chat_id']]['in_seq_no']++;
|
||||
if ($update['message']['decrypted_message']['layer'] >= 17) {
|
||||
$this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['layer'];
|
||||
if ($update['message']['decrypted_message']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) {
|
||||
$this->notify_layer($update['message']['chat_id']);
|
||||
}
|
||||
}
|
||||
$update['message']['decrypted_message'] = $update['message']['decrypted_message']['message'];
|
||||
$this->handle_decrypted_update($update);
|
||||
}
|
||||
|
@ -24,14 +24,14 @@ trait SeqNoHandler
|
||||
foreach ($this->secret_chats[$chat_id]['incoming'] as $message) {
|
||||
if (isset($message['decrypted_message']['in_seq_no'])) {
|
||||
if (($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2 < $last) {
|
||||
unset($this->secret_chats[$chat_id]);
|
||||
$this->discard_secret_chat($chat_id);
|
||||
throw new \danog\MadelineProto\SecurityException('in_seq_no is not increasing');
|
||||
}
|
||||
$last = ($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2;
|
||||
}
|
||||
}
|
||||
if ($seqno > $this->secret_chats[$chat_id]['out_seq_no'] + 1) {
|
||||
unset($this->secret_chats[$chat_id]);
|
||||
$this->discard_secret_chat($chat_id);
|
||||
throw new \danog\MadelineProto\SecurityException('in_seq_no is too big');
|
||||
}
|
||||
|
||||
@ -43,14 +43,17 @@ trait SeqNoHandler
|
||||
$seqno = ($seqno - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2;
|
||||
$C = 0;
|
||||
foreach ($this->secret_chats[$chat_id]['incoming'] as $message) {
|
||||
if (isset($message['decrypted_message']['out_seq_no']) && $C !== $this->secret_chats[$chat_id]['in_seq_no'] - 1) {
|
||||
var_dump($message);
|
||||
if (isset($message['decrypted_message']['out_seq_no']) && $C < $this->secret_chats[$chat_id]['in_seq_no']) {
|
||||
if (($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2 !== $C) {
|
||||
$this->discard_secret_chat($chat_id);
|
||||
throw new \danog\MadelineProto\SecurityException('out_seq_no hole: should be '.$C.', is '.(($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2));
|
||||
} else {
|
||||
$C++;
|
||||
}
|
||||
}
|
||||
}
|
||||
var_dump($C, $seqno);
|
||||
if ($seqno < $C) { // <= C
|
||||
\danog\MadelineProto\Logger::log(['WARNING: dropping repeated message with seqno '.$seqno]);
|
||||
$this->secret_chats[$chat_id]['in_seq_no']--;
|
||||
@ -58,7 +61,7 @@ trait SeqNoHandler
|
||||
return false;
|
||||
}
|
||||
if ($seqno > $C) { // > C+1
|
||||
unset($this->secret_chats[$chat_id]);
|
||||
$this->discard_secret_chat($chat_id);
|
||||
throw new \danog\MadelineProto\SecurityException('WARNING: out_seq_no gap detected ('.$seqno.' > '.$C.')!');
|
||||
return false;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user