Questo codice rappresenta una rudimentale implementazione dell'algoritmo X3DH utilizzato da WhatsApp e Signal per garantire la segretezza delle conversazioni. La comunicazione avviene attraverso due client collegati ad un server, posto all'indirizzo '127.0.0.1/8080' (localhost, porta 8080). Nel caso dell'implementazione base non è prevista la signature delle chiavi, ma semplicemente lo scambio tramite Diffie-Hellman. Per l'implementazione avanzata, invece, l'ellittica utilizzata per la generazione delle chiavi segrete e delle chiavi pubbliche è CurveX25519, la quale fornisce chiavi da 256 bit, mentre l'algoritmo per firmare e autenticare le chiavi pubbliche dei client è EdDSA, basato sempre sulla curva X25519.
Installa i pacchetti richiesti spostandoti nella cartella contenente il file requirements.txt ed esegui
pip install -r requirements.txt
- server.py genera un server, di default all'indirizzo '127.0.0.1/8080' (localhost, porta 8080). Il suo compito è memorizzare e trasmettere le chiavi pubbliche e i messaggi crittografati da un client all'altro.
- client.py genera un client e lo collega al server. Il suo compito è generare le chiavi pubbliche e private e consentire lo scambio di messaggi con l'altro client.
- generate_keys.py calcola le chiavi pubbliche e private, le shared key e il segreto condiviso.
- generate_prime.py genera un numero primo di n bit (basato sul test di Rabin-Miller).
- generator_finder.py calcola un generatore per il gruppo Zp*.
- nice_text.py serve per centrare e incorniciare i titoli delle chat.
- server.py genera un server, di default all'indirizzo '127.0.0.1/8080' (localhost, porta 8080). Il suo compito è memorizzare e trasmettere le chiavi pubbliche e i messaggi crittografati da un client all'altro.
- client.py genera un client e lo collega al server. Il suo compito è generare le chiavi pubbliche e private e consentire lo scambio di messaggi con l'altro client.
- generate_keys.py contiene la funzione concat_KDF, la quale calcola il segreto condiviso tramite KDF (Key Derivation Function).
- nice_text.py serve per centrare e incorniciare i titoli delle chat.
client.py e server.py simulano una conversazione.
- Apri una finestra del terminale nella cartella ed esegui
python server.py
per avviare il server
- Apri altre due terminali nella cartella ed esegui
python client.py
in entrambe, immettendo Alice e Bob come nickname (o i nickname che vuoi).
Il server si avvia silenziosamente, mentre entrambi i client comunicano l'apertura della chat e richiedono l'inserimento dei nickname. A questo punto è possibile per entrambi i client avviare una conversazione crittografata attraverso il server. Per chiudere i due client si deve ricorrere due volte al KeyboardInterrupt (CTRL + C) dal terminale per ognuno di essi; in questo caso, il lancio di eccezioni nei due terminali non comporterà alcun problema per quanto riguarda la riuscita della chat. Il server si spegnerà silenziosamente.
Vengono generati quattro file:
- chat.txt è il file che contiene la chat dal punto di vista del frontend e contiene solamente i messaggi della conversazione, riportati con il formato [ora , mittente , messaggio].
- public_chat.txt è il file che contiene la chat dal punto di vista di un agente esterno (attaccante) che controlli il movimento dei pacchetti tra i client e il server e che possa leggerne il contenuto (cifrato).
- secret_chat_<utente 1>.txt e secret_chat_<utente 2>.txt sono i file che contengono le chat dal punto di vista dei due utenti (<utente 1> e <utente 2>), in cui vengono riportate le chiavi segrete e i processi di decrittazione dei messaggi.
In entrambe le directory GUI_* è contenuto il codice per simulare una chat fra i due utenti, i cui messaggi vengono cifrati con gli stessi metodi dell'implementazione base e dell'implementazione avanzata. Per avviare la GUI basta eseguire i seguenti passaggi:
- Aprire due finestre del terminale nella cartella GUI ed esegui il primo comando in una finestra e poi il secondo comando nell'altra:
python client_1.py
python client_2.py
se si vuole vedere la chat in chiaro, mentre se ci si vuole mettere nei panni di un attaccante che intercetta i messaggi, si esegue come prima
python client_1.py ciphered
python client_2.py ciphered
- Inserire i nickname dei due utenti, poi si può iniziare a digitare nelle box delle due finestre. Una finestra sarà la chat dal punto di vista del primo utente, mentre l'altra sarà la chat dal punto di vista del secondo utente.
- Per chiudere la conversazione è sufficiente uscire dalle due finestre.
- L'implementazione tramite il modulo socket di Python ha dei problemi noti con Ubuntu, i quali non garantiscono sempre l'invio corretto dei dati e, di conseguenza, la loro corretta valutazione da parte del programma, generando possibilmente delle eccezioni.
SOLUZIONE: Modificare la porta del socket del server in server.py da 8080 ad un numero maggiore di 1024 e, conseguentemente, il numero di porta all'interno di client.py. In seguito riavviare i programmi.
- La chiusura del processo server.py durante l'esecuzione dei due programmi client comporterà un'eccezione all'interno dei due terminali client.
SOLUZIONE: Interrompere l'esecuzione di tutti i programmi coinvolti con KeyboardInterrupt (CTRL + C). Modificare la porta del socket del server in server.py da 8080 ad un numero maggiore di 1024 e, conseguentemente, il numero di porta all'interno di client.py. In seguito riavviare i programmi.