Descrizione originale del plugin
| Riepilogo | Discourse Encrypt abilita la messaggistica privata e crittografata tra gli utenti finali. Tutte le informazioni sensibili sono memorizzate in modo sicuro sul server e vengono crittografate e decifrate solo lato client. | |
| Link al repository | https://github.com/discourse/discourse-encrypt | |
| Guida all’installazione | Come installare i plugin in Discourse |
Tre semplici passaggi per utilizzare questo plugin
- Abilita la crittografia e attiva il dispositivo corrente.
- Invia un messaggio crittografato. Anche il destinatario deve aver abilitato la crittografia.
Facoltativamente, puoi determinare il tempo dopo il quale l’intero messaggio o un post specifico verrà distrutto permanentemente.
- Leggi i messaggi segreti. La crittografia deve essere attivata prima per leggerli.
Nota: in questo esempio, all’utente è stato richiesto nuovamente la chiave cartacea perché la crittografia era stata disattivata (effettuando il logout o disattivandola esplicitamente dalla schermata delle preferenze).
Informazioni tecniche
Questo plugin offre agli utenti la possibilità di comunicare in modo sicuro tramite Discourse, utilizzando un sistema di crittografia end-to-end. La maggior parte della logica del plugin è implementata lato client, mentre il server gestisce solo informazioni pubbliche o crittografate. Non vengono crittografati i metadati dei post, come i nomi dei partecipanti alla conversazione, l’ora di pubblicazione, i like, le piccole azioni, ecc.; i file caricati sono crittografati, ma la loro presenza non lo è perché il sistema deve associare i caricamenti ai post per evitarne l’eliminazione.
L’intero codice è open-source e gli appassionati di sicurezza sono invitati a esaminarlo. Per ulteriori informazioni, non esitare a contattarmi o il team. ![]()
leggi altro...
Riepilogo
L’obiettivo di questo plugin è garantire l’integrità e la riservatezza dei contenuti crittografati, proteggendoli da fughe di informazioni e utenti non autorizzati. Le sezioni seguenti descrivono la modalità operativa usuale, gli algoritmi utilizzati e i modelli di minaccia.
Per utilizzare questo sistema, gli utenti si registrano una volta generando un’“identità utente” composta da due chiavi RSA da 4096 bit, una per la crittografia e l’altra per la firma. Gli utenti possono esportare la propria “identità” per conservarla in modo sicuro o memorizzarla sul server, crittografata dopo aver generato una chiave cartacea. Questi due metodi servono come backup o per registrare nuovi dispositivi.
Le chiavi cartacee (ispirate a RFC 1751 e BIP-39) sono chiavi leggibili dall’uomo utilizzate per memorizzare in modo sicuro l’“identità utente” sul server. Una chiave cartacea è composta da 12 parole casuali, scelte da un elenco di 2048 parole, offrendo 121 bit di entropia (la prima parola è utilizzata come etichetta). Per crittografare l’“identità utente” con una chiave cartacea, il sistema deriva prima la chiave di crittografia utilizzando PBKDF2 per allungare la chiave cartacea in una chiave AES-GCM da 256 bit.
Creazione di un post crittografato
Per creare un nuovo post, l’utente (il suo browser):
-
firma il contenuto del post corrente utilizzando la propria chiave di firma privata;
-
genera una nuova “chiave del topic” (una chiave AES-256-GCM) che verrà utilizzata per crittografare il post, alcuni metadati del post e il titolo del nuovo topic (se disponibile);
-
recupera le chiavi pubbliche di tutti i partecipanti e crittografa la “chiave del topic” per ciascuno di essi;
-
invia al server il post crittografato (codificato in Base64) e le chiavi del topic crittografate (anch’esse codificate in Base64) di ciascun partecipante.
Il pseudocodice per l’operazione di crittografia sarebbe qualcosa del genere:
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
Lettura di un post crittografato
Per leggere un post, l’utente (il suo browser) :
-
recupera il payload del post crittografato (testo in chiaro del post e firma) e la chiave del topic crittografata;
-
utilizza la propria chiave di crittografia privata per decifrare la chiave del topic crittografata;
-
utilizza la chiave del topic decifrata per decifrare il payload del post crittografato;
-
recupera la chiave di firma pubblica dell’autore e verifica la firma del post.
Suite di algoritmi
Questo plugin fa ampio uso delle primitive crittografiche implementate nell’API Web Crypto, disponibili in tutti i browser moderni supportati da Discourse (tranne Internet Explorer).
-
getRandomValuesPRNG: Genera chiavi cartacee e IV casuali a 96 bit. -
PBKDF2: Allunga le chiavi cartacee a 132 bit fino a chiavi a 256 bit, utilizzate per crittografare le “identità utente”.
-
AES-256-GCM: Utilizzato per crittografare il contenuto di ogni post. Offre anche autenticazione producendo un tag di autenticazione a 128 bit, ma questo è un aspetto meno importante poiché i post sono verificati utilizzando una firma generata dall’autore (vedi passaggio 1 sopra).
-
RSA-OAEP: Utilizzato per crittografare le “chiavi del topic” e le “identità utente” per un archiviazione sicura sul server. Tutte le chiavi RSA-OAEP sono lunghe 4096 bit.
-
RSA-PSS: Utilizzato per firmare il contenuto di ogni post per verificarne l’autenticità. Tutte le chiavi RSA-PSS sono lunghe 4096 bit.
Primitive
Il sistema utilizza un insieme di primitive costruite su quelle fornite dal browser tramite Web Cryptography API.
-
encrypt e decrypt: Utilizzate per crittografare e decifrare il contenuto dei post.
encryptaccetta un JSON, una chiave AES-256-GCM e una chiave pubblica RSA-PSS e restituisce una singola stringa codificata in Base64;decryptaccetta una stringa codificata in Base64 e una chiave AES-256-GCM e restituisce l’oggetto JSON iniziale; -
verify: Utilizzato per verificare il contenuto dei post dopo la decifratura;
-
exportKey e importKey: Utilizzati per esportare e importare le “chiavi del topic”;
-
exportIdentity e importIdentity: Utilizzati per esportare e importare le “identità utente”.
Tipi di chiavi:
-
chiavi del topic (AES-256-GCM)
- utilizzate per crittografare ogni post in un topic (i post sono crittografati singolarmente)
- sono generate per topic, lato client dall’autore originale utilizzando la primitive
generateKeydell’API WebCrypto - sono crittografate con la chiave pubblica dell’utente per ogni utente che ha accesso al topic specifico utilizzando la primitive
wrapKeydell’API WebCrypto - sono memorizzate (crittografate) lato server per ogni utente in
PluginStore
-
coppia di chiavi RSA (chiave pubblica e privata) (RSA-OAEP e RSA-PSS, 4096 bit)
- utilizzate per crittografare tutte le chiavi del topic a cui un utente ha accesso
- sono generate per utente, lato client dall’autore originale utilizzando la primitive
generateKeydell’API WebCrypto e condivise tra tutti i dispositivi dell’utente - lato server: l’identità pubblica è memorizzata come esportata dal client, ma l’identità privata sarà sempre crittografata con la chiave della passphrase
- lato client: le chiavi pubblica e privata sono memorizzate come
CryptoKeyin IndexedDb; se non possibile, verrà utilizzatowindow.localStorage(in Safari)
-
chiavi passphrase (derivate utilizzando PKBDF2 con 128.000 iterazioni)
- utilizzate per crittografare le “identità utente” per un archiviazione sicura sul server
- derivate da una chiave cartacea (o dalla passphrase dell’utente per motivi di compatibilità)
Modelli di minaccia
Istanza di Discourse compromessa
Un attaccante che può iniettare codice potrebbe in teoria accedere a informazioni crittografate servendo codice dannoso, che decifra il contenuto crittografato e invia i post in testo in chiaro a un altro server. Per rendere ciò possibile, è sufficiente avere accesso a un account amministratore e creare un componente tema con il codice dannoso.
I meccanismi di protezione predefiniti come CSP possono rilevare e mitigare gli attacchi Cross Site Scripting (XSS) che potrebbero anche rappresentare un modo per iniettare codice dannoso.
Attacco Man-in-the-Middle
Negli attacchi Man-in-the-Middle, l’attaccante intercetta la comunicazione tra l’utente e il server, dandogli la possibilità di leggerla o modificarla. Poiché il plugin crittografa tutto prima dell’invio, un attaccante non può decifrare nulla semplicemente ascoltando. Allo stesso modo, poiché le informazioni sono autenticate, l’attaccante non può modificarle.
Tuttavia, l’attaccante potrebbe servire codice dannoso all’utente e seguire un attacco simile a quello presentato nella sezione precedente. Questo è parzialmente mitigato da HTTPS, che riduce notevolmente la probabilità di attacco.
Note
Il plugin ha già una breve storia, visibile esplorando il codice sorgente e notando le due implementazioni del protocollo v0 (iniziale, versione alpha-beta) e v1. Il protocollo v0 non è più utilizzato per crittografare nuovi post, ma è mantenuto per continuare a decifrare quelli vecchi. Il nuovo protocollo include l’autenticità dei testi cifrati e tutti i post sono firmati con la chiave privata dell’autore.
