Protocolo MTProto

Descrição Geral

O protocolo é projetado para acesso a um servidor de API de aplicativos executados em dispositivos móveis. Deve ser enfatizado que um navegador da web não é um tal pedido.

O protocolo é subdividido em três componentes praticamente independentes:

  • Componente de alto nível (linguagem de consulta API): define o método pelo qual as consultas de API e as respostas são convertidas em mensagens binárias.
  • Camada Criptográfica (autorização): define o método pelo qual as mensagens são criptografados antes de serem transmitidos através do protocolo de transporte.
  • Componente de transporte: define o método para o cliente e o servidor para transmitir mensagens sobre algum outro protocolo de rede existente (como, http, https, TCP, UDP).

mtproto_encryptacao

Nota 1

Cada mensagem de texto sem formatação para ser criptografados em MTProto sempre contém os seguintes dados a ser verificado quando decifrando a fim de tornar o sistema robusto contra problemas conhecidos com os componentes:

  • sal servidor (64-Bit)
  • identificação de sessão
  • número de seqüência de mensagem
  • comprimento da mensagem
  • tempo

Resumo breve dos componentes

Componentes de Alto Nível (RPC Query Language / API)

Do ponto de vista do componente de alto nível, o cliente e o servidor trocam mensagens dentro de uma sessão. A sessão está ligada ao dispositivo cliente (a aplicação, para ser mais exato) em vez de uma ligação de HTTP / HTTPS / TCP específico. Além disso, cada sessão está ligada a uma chave de identificação de utilizador, através da qual a autorização é efetivamente realizada.

Várias ligações a um servidor podem ser abertas; mensagens podem ser enviadas em qualquer direção através de qualquer uma das conexões (a resposta a uma consulta não é necessariamente devolvida pela mesma conexão que realizou a consulta original, embora na maioria das vezes, esse é o caso, no entanto, em nenhum caso pode ser uma mensagem devolvida através de uma ligação pertencente a uma sessão diferente). Quando o protocolo UDP é utilizado, uma resposta pode ser retornada por um endereço de IP diferente do que aquele a que a consulta tinha sido enviada.

Existem vários tipos de mensagens:

  • Chamadas RPC (cliente para servidor): chamadas para métodos de API
  • Respostas RPC (servidor para cliente): resultados de chamadas RPC
  • Confirmação de mensagem recebida(ou melhor, notificação de status de um conjunto de mensagens)
  • Consulta de status Mensagem
  • Mensagem concatenada ou recipiente (um recipiente que contém várias mensagens, necessário para enviar várias chamadas RPC de uma só vez através de uma conexão HTTP, por exemplo, também, um recipiente pode apoiar gzip).

Do ponto de vista dos protocolos de nível mais baixo, uma mensagem é um fluxo de dados binários alinhados ao longo de um limite de 4 ou 16 bytes. Os primeiros vários campos da mensagem são fixos e são utilizados pelo sistema de criptografia / autorização.

Cada mensagem, quer individualmente ou dentro de um recipiente, composto por um identificador de mensagem (64 bits, ver abaixo), um número de sequência de mensagem dentro de uma sessão (32 bits), o comprimento (do corpo da mensagem em bytes, 32 bits), e um corpo (qualquer tamanho que é um múltiplo de 4 bytes). Além disso, quando um recipiente ou uma única mensagem é enviada, um cabeçalho interno é adicionado no topo (ver abaixo), então a totalidade da mensagem é criptografada, e um cabeçalho exterior é colocada na parte superior da mensagem (um de 64 bits identificador de chave e uma chave de mensagem de 128 bits).

corpo da mensagem consiste normalmente em um tipo de mensagem 32-bit seguido por parâmetros dependentes do tipo. Em particular, cada função de RPC tem um tipo de mensagem correspondente. Para mais detalhes, ver dados binários serialização , Protocolo Celular: Mensagens de Serviço .

Todos os números são escritos no formato little endian. No entanto, um número muito grande (2048 bits) usados ​​na RSA e DH estão escritos no formato big endian porque é isso que a biblioteca OpenSSL faz.

Autorização e criptografia

Antes que uma mensagem (ou uma mensagem de várias vias) inicie a transmissão através de uma rede que utiliza um protocolo de transporte, que é criptografada de uma certa forma, um cabeçalho exterior é adicionado no topo da mensagem que é um identificador de chave de 64-bits ( que identifica de forma única uma chave de autorização para o servidor, bem como o utilizador) e uma chave de mensagem de 128 bits. Uma chave de usuário junto com a chave da mensagem define uma chave de 256 bits real que é o que criptografa a mensagem usando a criptografia AES-256. Note-se que a parte inicial da mensagem a ser encriptada contém dados variáveis ​​(sessão de mensagem, ID, número de sequência, salt server) que, obviamente, influencia a chave de mensagem (e, portanto, a chave AES e iv). A chave de mensagem é definido como os 128 bits de ordem inferior do SHA1 do corpo da mensagem (incluindo sessão, mensagem de identificação, etc). Mensagens de várias partes são criptografadas como uma única mensagem.

Para uma especificação técnica, ver Protocolo Celular: Descrição Detalhada
A primeira coisa que um aplicativo cliente deve fazer é criar uma chave de autorização que normalmente é gerado quando é executado pela primeira vez e quase nunca muda.

O inconveniente principal do protocolo é que se um intruso interceptar passivamente as mensagens e, em seguida, de alguma forma, apropriando-se da chave de autorização (por exemplo, por roubar um dispositivo) será capaz de decifrar todas as mensagens interceptadas a posteriori. Isso provavelmente não é um grande problema (por roubar um dispositivo, também se poderia ter acesso a todas as informações armazenadas em cache no dispositivo sem descriptografar qualquer coisa); no entanto, podem ser tomadas as seguintes medidas para superar este problema:

  • As chaves de sessão gerada utilizando o protocolo de Diffie-Hellman, e usado em conjunto com a autorização das chaves de mensagem e para seleccionar parâmetros de AES. Para criar estes, a primeira coisa que um cliente deve fazer depois de criar uma nova sessão é enviar uma consulta RPC especial ao servidor (“gerar chave de sessão”) ao qual o servidor irá responder, após o que todas as mensagens subsequentes dentro da sessão são criptografados usando o chave de sessão também.

 

  • Protegendo a chave armazenada no dispositivo cliente com um (texto) de senha; esta senha nunca é armazenado na memória e é inserido por um usuário ao iniciar a aplicação ou com maior frequência (dependendo das configurações de aplicativos).

 

  • Os dados armazenados (em cache) no dispositivo do usuário também pode ser protegido por criptografia usando uma chave de autorização que, por sua vez, é para ser protegido por senha. Em seguida, uma senha será necessária para obter acesso ainda a esses dados.

Sincronização de Tempo

Se o tempo do cliente diverge amplamente do horário do servidor, um servidor pode começar a ignorar mensagens de clientes, ou vice-versa, por causa de um identificador de mensagem inválido (que está intimamente relacionado com o tempo de criação). Sob estas circunstâncias, o servidor envia ao cliente uma mensagem especial contendo a hora correta e um determinado sal de 128 bits (quer explicitamente fornecido pelo cliente num pedido de sincronização RPC especial ou igual a chave da última mensagem recebida do cliente durante a sessão atual). Esta mensagem pode ser o primeiro em um recipiente que inclui outras mensagens (se a diferença de tempo é significativa mas ainda não resultar em mensagens do cliente a ser ignorado).

Tendo recebido tal uma mensagem ou um recipiente contendo-lo, o cliente efetua primeiro uma sincronização de tempo (na verdade, simplesmente armazenar a diferença entre a hora do servidor e as suas próprias para ser capaz de calcular o tempo “correta” no futuro) e, em seguida, verifica que os identificadores de mensagem para correção.

Onde tem sido negligenciada uma correção, o cliente terá que gerar uma nova sessão para assegurar a monotonia de identificadores de mensagem.

Transporte

Permite a entrega de contêineres criptografados juntamente com o cabeçalho externo (a seguir, Payload) do cliente para o servidor e para trás. Existem três tipos de transporte:

  • HTTP
  • TCP
  • UDP

Examinaremos os dois primeiros tipos.

Transporte HTTP

Implementado através de HTTP / 1.1 (com keepalive) que funciona sobre o tradicional porta TCP 80. HTTPS não é utilizado; o método de criptografia acima é usado em vez disso.

Uma conexão HTTP está ligado a uma sessão (ou melhor, a sessão + identificador de chave) especificado na consulta mais recente do usuário recebido; normalmente, a sessão é o mesmo em todas as consultas, mas proxies HTTP astutos que pode corromper. Um servidor não pode retornar uma mensagem em uma conexão HTTP, a menos que ele pertence à mesma sessão, ea menos que seja a vez do servidor (uma solicitação de HTTP foi recebido do cliente para que uma resposta não foi enviada até o momento).

A disposição geral é como se segue. O cliente abre uma ou mais conexões HTTP keepalive para o servidor. Se uma ou mais mensagens necessitam de ser enviados, eles são feitos numa carga que é seguido por um pedido POST para o URL / API para que a carga é transmitida como dados. Além disso, Content-Length , Keepalive e Host são cabeçalhos HTTP válidos.

Tendo recebido a consulta, o servidor pode ou esperar um pouco (se a consulta exige uma resposta após um curto tempo de espera) ou imediatamente devolver uma resposta fictício (apenas reconhecendo o recebimento do container). Em qualquer caso, a resposta pode conter qualquer número de mensagens. O servidor pode, ao mesmo tempo enviar outras mensagens que poderia estar segurando para a sessão.

Além disso, existe uma consulta RPC longo sondagem especial (válido somente para conexões HTTP) que transmite a máxima T. tempo limite Se o servidor tiver mensagens para a sessão, eles são devolvidos imediatamente; caso contrário, um estado de espera é inserido até que o servidor tem uma mensagem para o cliente ou T segundos se passaram. Se há eventos ocorrem no período de t segundos, uma resposta manequim é devolvido (mensagem especial).

Se um servidor deve enviar uma mensagem para um cliente, ele verifica para uma conexão HTTP que pertence à sessão e é necessária na “responder a um pedido de HTTP” estado (incluindo a longo sondagem) após o que a mensagem é adicionada ao recipiente de resposta a conexão e enviados para o usuário. Em um caso típico, há algum tempo de espera adicional (50 milissegundos) contra a eventualidade de que o servidor terá em breve mais mensagens para a sessão.

Se nenhuma conexão HTTP adequado estiver disponível, as mensagens são colocadas em fila de envio da sessão atual. No entanto, eles encontram seu caminho lá de qualquer maneira até que o recebimento é explícita ou indiretamente confirmada pelo cliente. Para o protocolo HTTP, enviar a consulta seguinte na mesma conexão HTTP é considerado como um reconhecimento implícito (não mais, do protocolo HTTP também requer que as confirmações explícitas ser enviados); em outros casos, o cliente deve retornar um reconhecimento expresso dentro de um tempo razoável (que pode ser adicionado a um recipiente para o pedido seguinte).

Importante: se a confirmação não chegar a tempo, a mensagem pode ser reenviado (possivelmente, em um recipiente diferente). As partes devem autonomamente estar pronto para isso e deve armazenar os identificadores das mensagens mais recentes recebidos (e ignorar tais duplicatas, em vez de ações de repetição). Para não ter os identificadores armazenados para sempre, existem mensagens especiais de coleta de lixo que se aproveitam de identificador de mensagem monotonicity.

Se a fila de envio transborda ou se as mensagens permanecem na fila por mais de 10 minutos, o servidor esquece-los (ou envia-los para trocar, nenhum gênio necessário). Isso pode acontecer ainda mais rápido, se o servidor está funcionando fora do espaço de buffer (por exemplo, por causa de problemas de rede graves, resultando em um grande número de conexões de tornar-se cortadas).

Transporte TCP

É muito semelhante ao transporte HTTP. Também pode ser implementada através da porta 80 (para penetrar todos os firewalls) e até mesmo usar os mesmos endereços IP do servidor. Nesta situação, o servidor de HTTP ou se entende protocolo TCP deve ser usado para a ligação, a partir dos primeiros quatro bytes de entrada (para HTTP, é POST).

Quando uma conexão TCP é criada, ela é atribuída à sessão (e a chave de autorização) transmitida na primeira mensagem do usuário e, posteriormente, utilizada exclusivamente para esta sessão (arranjos de multiplexação não são permitidos).

Se uma carga (maço) tem de ser transmitida a partir do servidor para o cliente ou do cliente ao servidor, ele é encapsulado como se segue: 4 bytes de comprimento são adicionados na parte da frente (para incluir o comprimento, o número de sequência, e CRC32; sempre divisível por 4) e 4 bytes com o número de sequência de pacote dentro desta ligação TCP (o primeiro pacote enviado é numerado 0, a próxima 1, etc.), e 4 CRC32 bytes no fim (comprimento, número de sequência, e carga útil em conjunto).

Há uma versão resumida do mesmo protocolo: se o cliente envia 0xef como o primeiro byte (** importante: ** Apenas antes de o primeiro pacote de dados), em seguida, tamanho do pacote é codificada por um único byte (0x01..0x7e = comprimento de dados dividido por 4, ou 0x7f seguido de 3 bytes de comprimento (pouco endian) dividido por 4), seguido pelos dados de si mesmos (número de seqüência e CRC32 não adicionado). Neste caso, as respostas do servidor de olhar o mesmo (o servidor não envia 0xef como o primeiro byte).

No caso de ser necessário o alinhamento de 4 bytes de dados, pode ser utilizada uma versão intermediária do protocolo original: se o cliente envia 0xeeeeeeee como o primeiro int (quatro bytes), em seguida, o comprimento do pacote é sempre codificada por quatro bytes como na versão original, mas o número de sequência e CRC32 são omitidos, diminuindo assim a dimensão total do pacote por 8 bytes.

O cheia, o intermediário e os versões abreviadas do protocolo tem suporte para reconhecimento rápido. Neste caso, o cliente coloca o bit de ordem mais alta comprimento no pacote de consulta, e o servidor responde com um especial de 4 bytes como um pacote separado. Eles são os 32 bits SHA1 de ordem superior da parte cifrada do pacote com o bit mais significativo definido para tornar claro que isto não é o comprimento de um pacote de resposta regular do servidor; se a versão resumida é usado, bswap é aplicada a esses quatro bytes.

Não há reconhecimentos implícitos para o transporte TCP: todas as mensagens devem ser reconhecidos de forma explícita. Na maioria das vezes, as confirmações são colocados num recipiente com a seguinte resposta de consulta ou se for transmitido em pouco tempo. Por exemplo, este é quase sempre o caso de mensagens de cliente que contêm consultas RPC: o reconhecimento chega normalmente com a resposta RPC.

No caso de um erro, o servidor pode enviar um pacote cuja carga consiste de quatro bytes como o código de erro.Por exemplo, o código de erro 403 corresponde às situações em que o erro HTTP correspondente teria sido devolvidos pelo protocolo HTTP.

 

Deixe um comentário