Descrição Original do Plugin
| Resumo | O Discourse Encrypt permite mensagens privadas e criptografadas entre usuários finais. Todas as informações sensíveis são armazenadas com segurança no servidor e são criptografadas e descriptografadas apenas no lado do cliente. | |
| Link do Repositório | https://github.com/discourse/discourse-encrypt | |
| Guia de Instalação | Como instalar plugins no Discourse |
Três passos fáceis para usar este plugin
- Ative a criptografia e ative o dispositivo atual.
- Envie uma mensagem criptografada. O destinatário também deve ter ativado a criptografia.
Opcionalmente, você pode determinar o tempo após o qual toda a mensagem ou postagem específica será destruída permanentemente.
- Leia mensagens secretas. A criptografia deve ser ativada primeiro para lê-las.
Nota: Neste exemplo, o usuário foi solicitado a fornecer a chave de papel novamente porque a criptografia foi desativada (ao fazer logout ou desativá-la explicitamente na tela de preferências).
Informações técnicas
Este plugin oferece aos usuários a possibilidade de se comunicar com segurança por meio do Discourse, usando um esquema de criptografia de ponta a ponta. A maior parte da lógica do plugin é implementada no lado do cliente, e o lado do servidor lida apenas com informações públicas ou criptografadas. Ele não criptografa nenhum metadado de postagem, como nomes de participantes na conversa, hora de postagem, curtidas, pequenas ações, etc; os uploads são criptografados, mas sua presença não é, porque o sistema deve associar uploads a postagens para evitar excluí-los.
Todo o código é de código aberto e entusiastas de segurança são bem-vindos para revisá-lo. Para qualquer informação adicional, não hesite em entrar em contato comigo ou com a equipe. ![]()
ler mais...
Resumo
O objetivo deste plugin é oferecer integridade e confidencialidade dos conteúdos criptografados e protegê-los contra vazamentos de informações e usuários não autorizados. As seções a seguir descrevem o modo de operação usual, os algoritmos utilizados e os modelos de ameaça.
Para usar este sistema, os usuários se inscrevem uma vez gerando uma “identidade de usuário” composta por duas chaves RSA de 4096 bits, uma para criptografia e outra para assinatura. Os usuários podem exportar sua “identidade” para guarda segura ou armazená-la no servidor, criptografada após gerar uma chave de papel. Esses dois métodos servem como backups ou são usados para inscrever novos dispositivos.
Chaves de papel (inspiradas em RFC 1751 e BIP-39) são chaves legíveis por humanos usadas para armazenar com segurança a “identidade de usuário” no servidor. Uma chave de papel consiste em 12 palavras aleatórias, escolhidas de uma lista de 2048 palavras, oferecendo 121 bits de entropia (a primeira palavra é usada como rótulo). Para criptografar a “identidade de usuário” com uma chave de papel, o sistema primeiro derivará a chave de criptografia usando PBKDF2 para esticar a chave de papel em uma chave AES-GCM de 256 bits.
Criando uma postagem criptografada
Para criar uma nova postagem, o usuário (seu navegador) irá:
-
assinar o conteúdo atual da postagem usando sua chave de assinatura privada;
-
gerar uma nova “chave de tópico” (uma chave AES-256-GCM) - que será usada para criptografar a postagem, alguns metadados da postagem e o título do novo tópico (se disponível);
-
buscar as chaves públicas de todos os participantes e criptografar a “chave de tópico” para cada um deles;
-
enviar ao servidor a postagem criptografada (codificada em Base64) e as chaves de tópico criptografadas (também codificadas em Base64) de cada participante.
O pseudocódigo para a operação de criptografia seria algo como:
signature = rsa_pss_sign(current_user.identity.sign_key.private, post.raw) # 1
topic_key = topic.key || generate_aes_256_gcm_key() # 2
encrypted_title = aes_256_gcm_encrypt(topic.title, topic_key) if topic.blank?
encrypted_post = aes_256_gcm_encrypt(signature + post.raw, topic_key)
encrypted_topic_keys = recipients.map { |r| rsa_oaep_encrypt(topic_key, r.identity.encryption_key.public) } # 3
$.put("/posts/create", { title: encrypted_title, raw: encrypted_post, keys: encrypted_topic_keys }) # 4
Lendo uma postagem criptografada
Para ler uma postagem, o usuário (seu navegador) irá:
-
buscar a carga útil da postagem criptografada (texto plano da postagem e assinatura) e a chave de tópico criptografada;
-
usar sua chave de criptografia privada para descriptografar a chave de tópico criptografada;
-
usar a chave de tópico descriptografada para descriptografar a carga útil da postagem criptografada;
-
buscar a chave pública de assinatura do autor e verificar a assinatura da postagem.
Conjunto de Algoritmos
Este plugin faz uso extensivo dos primitivos criptográficos implementados na Web Crypto API, que estão disponíveis em qualquer um dos navegadores modernos suportados pelo Discourse (exceto Internet Explorer).
-
getRandomValuesPRNG: Gera chaves de papel e IVs aleatórios de 96 bits. -
PBKDF2: Estica as chaves de papel de 132 bits para chaves de 256 bits, usadas para criptografar “identidades de usuário”.
-
AES-256-GCM: Usado para criptografar o conteúdo de cada postagem. Também oferece autenticação produzindo uma tag de autenticação de 128 bits, mas este é um aspecto menos importante porque as postagens são verificadas usando uma assinatura gerada pelo autor (veja o passo 1 acima).
-
RSA-OAEP: Usado para criptografar “chaves de tópico” e “identidades de usuário” para guarda segura no servidor. Todas as chaves RSA-OAEP têm 4096 bits de comprimento.
-
RSA-PSS: Usado para assinar o conteúdo de cada postagem para verificar autenticidade. Todas as chaves RSA-PSS têm 4096 bits de comprimento.
Primitivos
O sistema usa um conjunto de primitivos construídos sobre os fornecidos pelo navegador via Web Cryptography API.
-
encrypt e decrypt: Usados para criptografar e descriptografar conteúdos de postagens.
encryptrecebe um JSON, uma chave AES-256-GCM e uma chave pública RSA-PSS e produz uma única string codificada em Base64;decryptrecebe uma string codificada em Base64 e uma chave AES-256-GCM e produz o objeto JSON inicial; -
verify: Usado para verificar conteúdos de postagens após descriptografia;
-
exportKey e importKey: Usados para exportar e importar “chaves de tópico”;
-
exportIdentity e importIdentity: Usados para exportar e importar “identidades de usuário”.
Tipos de chaves:
-
chaves de tópico (AES-256-GCM)
- usadas para criptografar cada postagem em um tópico (postagens são criptografadas individualmente)
- são geradas por tópico, no lado do cliente pelo autor original usando o primitivo API
generateKeydo WebCrypto - são criptografadas com a chave pública do usuário para cada usuário que tem acesso ao tópico específico usando o primitivo API
wrapKeydo WebCrypto - são armazenadas (criptografadas) no lado do servidor para cada usuário em
PluginStore
-
par de chaves RSA (chaves pública e privada) (RSA-OAEP e RSA-PSS, 4096 bits)
- usadas para criptografar todas as chaves de tópico a que um usuário tem acesso
- são geradas por usuário, no lado do cliente pelo autor original usando o primitivo API
generateKeydo WebCrypto e compartilhadas entre todos os dispositivos do usuário - lado do servidor: a identidade pública é armazenada conforme exportada pelo cliente, mas a identidade privada será sempre criptografada com a chave de senha
- lado do cliente: chaves pública e privada são armazenadas como
CryptoKeyno IndexedDb; se não for possível, usaráwindow.localStorage(no Safari)
-
chaves de senha (derivadas usando PKBDF2 com 128.000 iterações)
- usadas para criptografar “identidades de usuário” para armazenamento seguro no servidor
- derivadas de uma chave de papel (ou senha do usuário para fins legados)
Modelos de Ameaça
Instância do Discourse Comprometida
Um invasor que possa injetar código poderia, em teoria, acessar informações criptografadas servindo código malicioso, que descriptografa o conteúdo criptografado e envia as postagens em texto plano para outro servidor. Para tornar isso possível, basta ter acesso a uma conta de administrador e criar um componente de tema com o código malicioso.
Mecanismos de proteção padrão, como CSP, podem detectar e mitigar ataques de Cross Site Scripting (XSS) que também podem representar uma maneira de injetar código malicioso.
Ataque Man-in-the-Middle
Em ataques Man-in-the-Middle, o invasor intercepta a comunicação entre o usuário e o servidor, dando-lhe a capacidade de ler ou alterá-la. Como o plugin criptografa tudo antes de enviar, um invasor não pode descriptografar nada apenas espionando. Da mesma forma, como as informações são autenticadas, o invasor não pode alterá-las.
No entanto, o invasor poderia servir código malicioso de volta ao usuário e seguir um ataque semelhante ao apresentado na seção anterior. Isso é parcialmente mitigado pelo HTTPS, que reduz consideravelmente a probabilidade de ataque.
Notas
O plugin já tem uma pequena história e isso pode ser visto ao navegar pelo código-fonte e notar as duas implementações do protocolo v0 (inicial, versão alpha-beta) e v1. O protocolo v0 não é mais usado para criptografar novas postagens, mas mantido para continuar descriptografando as antigas. O novo protocolo inclui autenticidade dos textos cifrados e todas as postagens são assinadas com a chave privada do autor.
