Nachrichten verschlüsseln für ein kleines Chat-Projekt



  • Hey Ho, Ho Hey!

    Ich spinne da gerade mit einem neune Projekt herum, was unter anderem auch einen Chat beinhalten soll. Privaten Chat, Gruppen Chat und Öffentlicher Chat. Wie man das ja eigentlich auch kennt.

    Öffentlich und Gruppe ist jetzt weniger ein Problem, die bleiben einfach unverschlüsselt. Hat seine Gründe. Privat jedoch möchte ich verschlüsseln.

    Nun habe ich mich ein bisschen umgeschaut. Libtomcrypt, crypto++, botan. Erst und letzt genannte Fälle haben ja auch eine ziemlich gute Dokumentation, aber entweder bin ich zu dämlich, daraus etwas zu machen, oder ich stehe irgendwo feste auf dem Schlauch.

    Im Prinzip stelle ich mir das so vor:

    Mit der Registrierung werden Keys erstellt. Public und Private. Der Public kommt in die Datenbank, private bleibt auf dem eigenen Rechner.

    Schreibt man nun mit einer Person, so wird beim Abschicken auf dem Rechner das Ganze mit dem publickey des Empfängers verschlüsselt und kommt dann erst in die Datenbank. Der Empfänger bekommt die Nachricht und die wird erst auf seinem Rechner mit seinem privatekey entschlüsselt.

    Ich bräuchte Starthilfe! Wohl gemerkt, bislang hatte ich noch nie etwas zu dem Thema gemacht. Es gibt wohl nicht eine Lib, wo man einfach nur Key und Nachricht in eine Funktion wirft und dann eine verschlüsselte Nachricht bekommt?





  • Verschlüsselung für Netzwerkverkehr? Da würde ich direkt auf TLS setzen. Das macht alles sauber und ordentlich. Deshalb meine Empfehlung: OpenSSL in Verbindung mit Boost::Asio.



  • @Zhavok Private Chats soll der Server wohl besser nicht mitlesen können.



  • @Swordfish Das eine schließt das andere ja nicht aus. Die Nachrichten können trotzdem auf dem Server mit AES verschlüsselt werden. Jedoch nur die Verschlüsselung mit AES wie bei deinem Link halte ich für Sergey Fährlich. Spätestens beim Schlüsselaustausch können schnell Fehler entstehen. Und wenn ich in einem Chat angemeldet bin, wo von Privatchat-Verschlüsselung die Rede ist, verlasse ich mich auf eine saubere Implementation von Leuten, die sich auf dem Gebiet auskennen. Sowas sollte man einfach nie selbst schreiben.



  • @Zhavok sagte in Nachrichten verschlüsseln für ein kleines Chat-Projekt:

    Die Nachrichten können trotzdem auf dem Server mit AES verschlüsselt werden.

    Das sollte wohl beim Client passieren bevor der Server die Nachricht über eine TLS-gesicherte Verbindung bekommt.

    @Zhavok sagte in Nachrichten verschlüsseln für ein kleines Chat-Projekt:

    Und wenn ich in einem Chat angemeldet bin, wo von Privatchat-Verschlüsselung die Rede ist, verlasse ich mich auf eine saubere Implementation von Leuten, die sich auf dem Gebiet auskennen. Sowas sollte man einfach nie selbst schreiben.

    Ähm. Der Link zeigt die Verwendung von crypto++ und redet nicht von Selberschreiben.



  • @Swordfish sagte in Nachrichten verschlüsseln für ein kleines Chat-Projekt:

    Ähm. Der Link zeigt die Verwendung von crypto++ und redet nicht von Selberschreiben.

    Und was macht man mit lediglich einer AES Verschlüsselung wenn man einen Chat vor Mitlesenden schützen will?



  • Hast ja recht. Besser RSA ^^
    War eben das erstbeste Beispiel zur Verwendung von crypto++ das mir über den Weg gelauft ist.



  • @Swordfish sagte in Nachrichten verschlüsseln für ein kleines Chat-Projekt:

    Hast ja recht. Besser RSA ^^

    Zum Beispiel. Das Problem bei asymmetrischen Verfahren, ist halt leider die Geschwindigkeit (RSA ist 100 mal langsamer als AES). Für einen Chat ist das sicher ausreichend, aber falls du (@Hirnfrei ) noch irgendwann Up-/Downloads hinzufügen möchtest, würde ich ein hybrides Verfahren benutzen.







  • Ach herrje, 2 Minuten nicht reingeschaut und schon musste ich ein ganzer Roman lesen!

    Erstmal danke für die Hinweise. RSA würde mir persönlich auch sehr gut gefallen. Oder OTR. Wobei es im Prinzip nur Spielerei ist. Ich wage es zu bezweifeln, dass dieses Programm grosse Verwendung finden wird. Ist eigentlich nur für eine Gruppe von uns hier gedacht und auch mehr aus einem Kneipengespräch was damit begann, dass man bei WhatsApp nie Termine abmachen sollte, da in Gruppen ohnehin so viel Schwachsinn geschrieben wird, dass wenn man nicht dauernd mitliest ganz schnell Termine verbummelt. Also selbst wenn es nicht so sicher ist, dass der BND nicht mitlesen kann, ist das auch kein Beinbruch. Mich reizt es jetzt aber, da auch eine Verschlüsslung einzubauen.

    Wo ich aber Wert drauf lege ist ganz klar, die Nachrichten sollen lokal verschlüsselt und entschlüsselt werden. Der Server soll damit nichts zu tun haben. Eben End-2-End.

    Ich kann nicht ausschliessen, dass da auch mal Bilder drüber sollen. Was würdest du dafür denn empfehlen und kannst du mich da auch auf den Weg bringen? Wie schon angemerkt, ich bin Neuling auf dem Gebiet.



  • Naja, das haben @Zhavok und ich ja grade durchgekaut:

    Public chat: Jeder Client sendet/empfängt zum/vom Server über eine mit TLS gesicherte Verbindung. Server verteilt die Nachrichten an die anderen Clients
    Private chat: Server vermittelt die IPs der Partner, Partner tauschen den mit irgendeinem Public-Key Verfahren (zB. RSA) verschlüsselten Session-Key, weitere Kommunikation findet Client-to-Client mit einem synchronen Verschlüsselungsverfahren (zB. AES) statt.



  • Wie sieht es denn mit GnuPG aus? Wäre das ratsam?



  • Also, GnuPG scheine ich zu verstehen. Nur hinter eins steige ich nicht. Was genau ist da jetzt der private und was der öffentliche Schlüssel?





  • also eigentlich verwendet man aes und den schlüssel dafür tauscht man über rsa aus. 😉

    soweit ich weiß kann man beides über openssl oder den windows crypto provider bekommen.



  • Also wenn ich das richtig verstanden habe, generiert GnuPG einen privaten und einen öffentlichen Schlüssel. In der Dokumentation wird aber von primary und sub gesprochen. Bin ich gerade am ausprobieren. Ich möchte ungerne den Schlüssel zum entschlüsseln verschicken müssen. Der soll schön auf dem lokalen System bleiben.


  • Mod

    @Hirnfrei sagte in Nachrichten verschlüsseln für ein kleines Chat-Projekt:

    Also wenn ich das richtig verstanden habe, generiert GnuPG einen privaten und einen öffentlichen Schlüssel. In der Dokumentation wird aber von primary und sub gesprochen. Bin ich gerade am ausprobieren. Ich möchte ungerne den Schlüssel zum entschlüsseln verschicken müssen. Der soll schön auf dem lokalen System bleiben.

    RTFM!?
    https://wiki.debian.org/Subkeys



  • Danke @SeppJ. Wieder was gelernt!

    Aber, ich muss um Rat fragen. Ich bin gerade dabei mir eine Funktion zu bauen, die ein Schlüsselpaar generiert. Da sieht bislang so aus:

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #include <gpgme.h>
    
    #include "t-support.h"
    
    gpgme_error_t gpgErr;
    
    gpgme_key_t prKey = NULL;
    gpgme_key_t puKey = NULL;
    
    bool keyGEN(string name, string email)
    {
    	gpgme_ctx_t ctx;
    	char *parms;
    	gpgme_genkey_result_t result;
    	gpgme_data_t out;
    	gpgme_key_t ekey[2] = {NULL, NULL};
    	
    	size_t csize = strlen("<GnupgKeyParms format=\"internal\">\n") + 2 +
    							strlen("Key-Type: RSA\n") + 2 +
    							strlen("Key-Length: 2048\n") + 2 +
    							strlen("Subkey-Type: ELG-E\n") + 2 +
    							strlen("Subkey-Length: 2048\n") + 2 +
    							strlen("Name-Real: \n") + 2 +
    							strlen(name.c_str()) + 2 +
    							strlen("Name-Comment: (pp=abc)\n") + 2 +
    							strlen("Name-Email: \n") + 2 +
    							strlen(email.c_str()) + 2 +
    							strlen("Expire-Date: 0\n") + 2 +
    							strlen("</GnupgKeyParms>\n") + 2;
    							
    	parms = (char *) malloc(csize);
    
    	sprintf(parms, "<GnupgKeyParms format=\"internal\">\n\
    Key-Type: RSA\n\
    Key-Length: 2048\n\
    Subkey-Type: ELG-E\n\
    Subkey-Length: 2048\n\
    Name-Real: %s\n\
    Name-Comment: (pp=abc)\n\
    Name-Email: %s\n\
    Expire-Date: 0\n\
    Passphrase: abc\n\
    </GnupgKeyParms>\n", name.c_str(), email.c_str());
    					
    	init_gpgme(GPGME_PROTOCOL_OpenPGP);
    
    	gpgme_set_armor(ctx, 1);
      
      	gpgErr = gpgme_new(&ctx);
    	if(gpgErr) return false;
    
    	gpgErr = gpgme_op_genkey(ctx, parms, NULL, NULL);
    	if(gpgErr) return false;
      
    	result = gpgme_op_genkey_result(ctx);
    
    	if(!result)
    	{
    		fprintf(stderr, "%s:%d: gpgme_op_genkey_result returns NULL\n", __FILE__, __LINE__);
    		return false;
    	}
    	
    	gpgErr = gpgme_get_key(ctx, result->fpr, &puKey, 0);
    	if(gpgErr) return false;
    
    	ekey[0] = puKey;
    
    	gpgErr = gpgme_op_export_keys(ctx, ekey, 0, out);
    	if(gpgErr) return false;
    
      	free(parms);
    	
    	return true;
    }
    

    Soweit funktioniert das auch, bis runter zu:

    gpgErr = gpgme_op_export_keys(ctx, ekey, 0, out);
    

    Da bekomme ich die Fehlermeldung:

    GPGME: Ungültiger Wert
    

    In der Beschreibung habe ich nun gelesen, diese Meldung heisst folgendes:

    if the operation completed successfully, GPG_ERR_INV_VALUE if keydata is not a valid empty data buffer
    

    Nachzulesen hier.

    Ich komme aber echt nicht hinter das Problem. Wie man im Code ja sehen kann, habe ich out nur deklariert. Da steht nichts drin und sie ist vom korrekten Typ. Aus Spass habe ich mal ein Beispiel zum exportieren von Keys compiliert und da kommt der gleiche Fehler.

    Hat jemand eine Idee?


Log in to reply