Verificação de Assinatura de Federação no Mastodon: Guia Passo a Passo de HTTP Signature
🔍 WiseChecker

Verificação de Assinatura de Federação no Mastodon: Guia Passo a Passo de HTTP Signature

Quando um servidor Mastodon recebe uma requisição ActivityPub de outra instância, ele precisa verificar se a requisição realmente se originou do ator declarado e não foi adulterada durante o trânsito. Sem essa verificação, um invasor poderia forjar mensagens, personificar usuários ou injetar spam na linha do tempo federada. O Mastodon utiliza HTTP Signatures, um padrão definido no rascunho IETF HTTP Signatures, para autenticar cada requisição entre servidores. Este guia explica as etapas exatas que o Mastodon realiza para validar uma HTTP Signature recebida, desde a análise do cabeçalho até a verificação do resumo criptográfico.

Principais Conclusões: Verificação de HTTP Signature na Federação do Mastodon

  • Análise do cabeçalho Signature: O Mastodon extrai o keyId, algoritmo, lista de cabeçalhos e valor da assinatura do cabeçalho HTTP Signature.
  • Recuperação da chave via keyId: O servidor busca a chave pública do ator a partir da URL especificada no campo keyId, geralmente armazenada como uma propriedade publicKey no perfil ActivityPub do ator.
  • Construção da string assinada: O Mastodon reconstrói a string assinada concatenando os valores dos cabeçalhos listados no parâmetro headers, separados por caracteres de nova linha.

ADVERTISEMENT

Por que o Mastodon Verifica HTTP Signatures em Requisições de Federação Recebidas

As instâncias do Mastodon se comunicam usando o protocolo ActivityPub, que depende de requisições HTTP POST para entregar atividades como Create, Follow e Like. Cada requisição carrega um payload no formato JSON-LD. Se um servidor aceitasse essas requisições sem autenticação, qualquer ator malicioso poderia enviar atividades falsas que parecem vir de um usuário legítimo em outra instância. As HTTP Signatures impedem isso permitindo que o servidor receptor verifique criptograficamente a identidade do remetente.

O processo de verificação depende de criptografia assimétrica. O ator remetente possui uma chave privada, e a chave pública é publicada como parte do perfil ActivityPub do ator, acessível via URL. O Mastodon nunca armazena chaves privadas de atores remotos. Em vez disso, ele busca a chave pública sob demanda e a usa para verificar a assinatura incluída no cabeçalho HTTP. Todo o processo é stateless, o que o torna escalável entre milhares de instâncias federadas.

O Papel do Cabeçalho HTTP Signature

O cabeçalho Signature é enviado pelo servidor de origem em cada requisição ActivityPub POST. Ele contém vários parâmetros: keyId, algorithm, headers e signature. O keyId é uma URL que aponta para a chave pública do ator. O parâmetro algorithm especifica o algoritmo de hash, geralmente rsa-sha256. O parâmetro headers lista quais cabeçalhos HTTP foram incluídos no cálculo da assinatura. O valor signature é o resultado codificado em base64 da assinatura dos valores dos cabeçalhos concatenados com a chave privada do ator.

Passo a Passo: Como o Mastodon Verifica uma HTTP Signature Recebida

  1. Extrair o cabeçalho Signature
    O servidor Mastodon receptor lê o cabeçalho Signature da requisição HTTP recebida. Ele analisa os pares chave-valor separados por vírgula para extrair keyId, algorithm, headers e signature. Se o cabeçalho estiver ausente ou malformado, o Mastodon rejeita a requisição imediatamente com uma resposta 401 Unauthorized.
  2. Resolver a chave pública do ator a partir da URL keyId
    O Mastodon pega o valor de keyId, que é uma URL como https://exemplo.instancia/users/alice#main-key. Ele faz uma requisição HTTP GET para essa URL para buscar o perfil ActivityPub do ator. A resposta deve incluir um objeto publicKey com um campo publicKeyPem contendo a chave pública RSA no formato PEM. O Mastodon armazena em cache essa chave por um curto período para reduzir buscas repetidas.
  3. Determinar quais cabeçalhos foram assinados
    O Mastodon lê o parâmetro headers do cabeçalho Signature. Este parâmetro lista os nomes dos cabeçalhos HTTP que o servidor remetente incluiu no cálculo da assinatura, por exemplo: (request-target) host date digest. Se o parâmetro headers estiver ausente, o Mastodon usa apenas date como padrão, mas versões modernas do Mastodon exigem os cabeçalhos (request-target) e digest por segurança.
  4. Reconstruir a string assinada
    O Mastodon constrói uma string pegando o valor de cada cabeçalho listado no parâmetro headers, na mesma ordem. Para cada cabeçalho, ele escreve o nome do cabeçalho em minúsculas, dois pontos, um espaço e o valor do cabeçalho. Cada par cabeçalho-valor é separado por um caractere de nova linha. O pseudo-cabeçalho especial (request-target) é substituído pelo método HTTP e caminho, por exemplo: post /inbox.
  5. Decodificar a assinatura e verificar com a chave pública
    O Mastodon decodifica o parâmetro signature em base64 para obter os bytes brutos da assinatura. Em seguida, ele usa a chave pública do passo 2 e o algoritmo especificado no cabeçalho para verificar a assinatura em relação à string assinada reconstruída. Para RSA-SHA256, o Mastodon calcula o hash SHA-256 da string assinada e tenta descriptografar a assinatura com a chave pública. Se o hash descriptografado corresponder ao hash calculado, a assinatura é válida.
  6. Verificar o cabeçalho digest (se presente)
    Se a requisição incluir um cabeçalho Digest, o Mastodon calcula o hash SHA-256 do corpo da requisição e compara com o valor no cabeçalho Digest. Isso garante que o corpo não foi modificado após a criação da assinatura. Se os digests não coincidirem, o Mastodon rejeita a requisição mesmo que a assinatura seja válida.
  7. Verificar a atualidade do cabeçalho date
    O Mastodon verifica o cabeçalho Date (ou Original-Date se configurado) para garantir que a requisição foi enviada nos últimos 30 segundos. Isso impede ataques de repetição, onde um invasor captura uma requisição assinada válida e a envia novamente mais tarde. Se o timestamp for muito antigo ou estiver no futuro por mais de 30 segundos, o Mastodon rejeita a requisição.

ADVERTISEMENT

Falhas Comuns de Verificação e Suas Causas Raiz

Erro "HTTP Signature Verification Failed" nos Logs do Servidor

Esse erro aparece quando a verificação criptográfica no passo 5 falha. A causa mais comum é uma incompatibilidade entre a chave pública que a instância remetente anuncia e a chave privada que ela usou para assinar a requisição. Isso pode acontecer após um administrador rotacionar o par de chaves do servidor, mas não atualizar o campo publicKey do ator no banco de dados. A correção é garantir que a propriedade publicKey no perfil ActivityPub do ator corresponda à chave privada usada pela aplicação remetente.

Erro "Key Not Found" ao Buscar o Ator

Se o Mastodon receptor não conseguir buscar o perfil do ator a partir da URL keyId, ele registra um erro "Key not found". Isso ocorre quando a instância remetente está fora do ar, a URL está incorreta ou o perfil do ator não inclui uma propriedade publicKey. O Mastodon tenta a busca até três vezes com um intervalo de um segundo entre as tentativas. Se a busca ainda falhar, a requisição é rejeitada. Os administradores devem verificar se o endpoint ActivityPub da instância remetente está acessível e retorna JSON-LD válido.

Erro "Digest Mismatch"

Uma incompatibilidade de digest indica que o corpo da requisição foi modificado após a criação da assinatura. Isso pode acontecer se um proxy ou balanceador de carga entre as duas instâncias alterar o corpo da requisição, por exemplo, comprimindo-o ou removendo espaços em branco. A correção é configurar a infraestrutura intermediária para passar o corpo da requisição inalterado. O Mastodon também suporta o cabeçalho Digest com o algoritmo SHA-256; se o proxy recalcular o digest, ele deve atualizar o cabeçalho de acordo.

Verificação de HTTP Signature: Mastodon vs Especificação ActivityPub

Item Implementação do Mastodon Especificação ActivityPub
Cabeçalhos assinados padrão (request-target) host date digest Recomenda (request-target) date
Algoritmo obrigatório Apenas RSA-SHA256 Suporta qualquer algoritmo listado no rascunho HTTP Signatures
Tolerância do cabeçalho Date 30 segundos Nenhuma tolerância específica definida
Verificação de Digest Obrigatória para requisições POST Opcional
Cache de chaves 10 minutos Não especificado

A implementação do Mastodon é mais rigorosa que a especificação ActivityPub para melhorar a segurança. O cabeçalho digest obrigatório e a curta tolerância de data reduzem a superfície de ataque para ataques de repetição e adulteração de corpo. No entanto, esse rigor pode causar problemas de compatibilidade com outros softwares do fediverso que implementam uma interpretação mais flexível do rascunho HTTP Signatures.

Após ler este guia, você pode rastrear a lógica de verificação nos logs do seu servidor quando ocorrerem erros de federação. Da próxima vez que vir uma mensagem "signature verification failed", verifique primeiro a URL keyId e a lista de cabeçalhos assinados. Para depuração avançada, ative o log detalhado na sua instância Mastodon definindo SINGLE_USER_MODE=false e VERBOSE_FEDERATION=true na configuração de ambiente para ver a string assinada exata que o Mastodon construiu.

ADVERTISEMENT