Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten

Added by timekeeper about 5 years ago

Auf Anwendungsebene möglichst transparente Verwendung einer sicheren Verschlüsselung (wie z.B. mit einem StandardPBEByteEncryptor von http://www.jasypt.org), da die Verwendung von SSL wegen der damit verbundenen Zertifikate in den allermeisten Fällen nicht praktikabel ist. Weder gibt es eine kostengünstige Möglichkeit zur Erstellung sicherer Zertifikate noch ist es dem Benutzer eines Clients zuzumuten, ein SSL-Zertifikat selbst zu erstellen. Damit muss man derzeit entweder auf eine sichere Datenübertragung verzichten oder einen Profi zur Hand haben, der die Einrichtung der Zertifikate übernimmt. Meist bleibt daher nur die unsichere Übertragung.

Idealerweise würde man in Simon.createNameLookup() nur noch eine boolsche Variable angeben, ob man einen verschlüsselten Transfer haben will oder nicht und der Rest würde automatisch funktionieren. Der Schlüssel könnte im Lookup zurückgegeben werden. Es sollte ein asymmetrische Verschlüsselung verwendet werden und jeder Client sollte einen eigenen Schlüssel bekommen. Da jasypt derzeit noch keine Stream-Verschlüsselung unterstützt, wäre der Dateitransfer u.U. ein Problem, da die zu verschlüsselnden Daten im Memory liegen müssen (oder ist es vielleicht doch kein Problem, da sowieso stückweise übertragen wird?)

Meines Erachten wäre das ein tolles Alleinstellungsmerkmal für SIMON!


Replies (10)

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Hallo,

schön wieder von dir zu hören.

Weder gibt es eine kostengünstige Möglichkeit zur Erstellung sicherer Zertifikate

Ich glaube das stimmt so nicht. Ob ich mir nun ein Passwort zur Verschlüsselung ausdenke, oder mir ein SSL-Zertifikat selbst erstelle: Beides ist ohne zuwirken von Dritten möglich und beides kostet nichts.

Es gibt die Möglichkeit der Verwendung einer zentralen Zertifizierungsstelle (kostenlos z.B. via cacert.org; Anleitung hier: http://dev.root1.de/projects/simon/repository/entry/trunk/doc/ssl_howto.txt) oder man ist seine eigene Zertifizierungsstelle. Für letzteres müsste ich noch eine Anleitung zusammenschreiben.

Kostenpflichtig wird es nur, wenn ich eine kostenpflichtige Zertifizierungsstelle bemühe. Aber das macht ja nur Sinn, wenn mit unbekannten kommuniziert wird. Beispielsweise im Emailverkehr. Da sollte der Empfänger dann kontrollieren können ob der Absender stimmt. Aber weder für SIMON noch für deine Anwendung wird das relevant sein. Denn dir reicht ja wenn der User im Server/Client das notwendige Passwort hinterlegt.

noch ist es dem Benutzer eines Clients zuzumuten, ein SSL-Zertifikat selbst zu erstellen

Ich denke da kommt es auch drauf an wie man das "verpackt". Im Endeffekt braucht ja der Server so wie jeder Client eine Schlüssel-Datei. Fertig. Die Erstellung der Files kann man ja über eine GUI lösen. Dann reicht es die jeweilige File beim jeweiligen Client bzw. Server benutzt wird. Damit wäre das für den Benutzer fast noch einfacher als mit einem Passwort: Er bekommt eine Datei, die muss er in der Anwendung angeben. Kein Passwort merken, keine Tippfehler.

Aber ich geb dir recht: Von Seiten des Entwicklers ist es relativ aufwendig.

Wie man jasypt in SIMON integriert muss ich mir mal noch anschauen. Theoretisch reicht es ja jasypt als Filter in die MINA Filterkette zu hängen. Aber ich hab da noch meine bedenken was das Senden der Pakete betrifft: Es könnte sein dass nicht nach jeder SIMON-Nachricht genug Daten für den nächsten Dekodier-Happen da sind und erst noch ein paar bytes von der nächsten Nachricht gelesen werden müssen. Somit könnte es hier und da längere Latenzen in der Nachrichten-Übertragung geben. Aber ich muss gestehen: Ich hab noch kein Plan wie jasypt intern genau arbeitet und ob nach jedem beliebigen Byte schon dekodiert werden kann. Wenn du hier mehr weißt: Lass mich an deinem Wissen Teil haben ;-)

Aber so generell stimme ich dir zu: Hier steckt noch potential für SIMON drin. Am liebsten wäre mit eine API-Schnittstelle mit der man eigene Verfahren recht easy an SIMON adaptieren kann, und z.B. jasypt mit passendem SIMON-Wrapper als optionales Paket zu SIMON zum Download zur verfügung gestellt wird. Somit wäre jasypt dann keine Vorraussetzung im Classpath um SIMON (ohne verschlüsselung) nutzen zu können.

Gruß
Alex

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Hab mal geschaut wie andere MINA Filter so aufgebaut sind. Scheinbar stellt die Verwendung von jasypt kein Problem dar: Filter müssen nicht byte-orientiert arbeiten. Sie können genauso gut Nachrichten-orientiert arbeiten. Sprich: Jede SIMON Nachricht wird für sich ver- und später wieder entschlüsselt.

Ich experimentiere damit noch ein wenig. Wenn ich ausreichend Zeit finde, dann könnte das Feature schon Ende kommender Woche fertig sein. Aber ich will nicht zu viel versprechen. Hausbau-Planung, eigentlicher Job sowie Kind/Familie geht erstmal vor...

Gruß
Alex

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Ach, es ist doch jedesmal das gleiche. Wenn ich etwas anfange, dann packt es mich auch ;-)

Die erste integration war gar nicht so schwer. Ein paar kleinere Hürden, aber die waren schnell eliminiert.

So, aktuell würde es so aussehen:

SIMON bietet folgendes Interface an:

public interface CustomEncryption {

    public byte[] encrypt(byte[] data);
    public byte[] decrypt(byte[] data);

}

Das kann man dann z.B. wie folgt implementieren:

import de.root1.simon.CustomEncryption;
import org.jasypt.encryption.pbe.StandardPBEByteEncryptor;

public class JasypSimonPBE implements CustomEncryption {

    private final StandardPBEByteEncryptor encryptor = new StandardPBEByteEncryptor();

    public JasypSimonPBE(String pw) {
        encryptor.setPassword(pw);
    }

    public byte[] encrypt(byte[] data) {
        return encryptor.encrypt(data);
    }

    public byte[] decrypt(byte[] data) {
        return encryptor.decrypt(data);
    }

}

Vor dem erstellen der Registry oder des Lookups auf Clientseite führt man dann folgendes aus:

Simon.setCustomEncryption(new JasypSimon("MySecretPW"));

Und schon wird die Verbindung mit Jasypt und dem gewählten Passwort verschlüsselt. Ich würde als optionales SIMON Modul die eine oder andere Jasypt-SIMON-Encryptor-Klasse als separates Projekt zur Verfügung stellen. Damit reduziert sich der Aufwand des Entwicklers auf das wählen der passendes CustomEncryption-Klasse, sowie das setzen dieser Klasse in SIMON.

Ein wenig optimierpotential gibt es noch. Was mir diesbezüglich spontan einfällt:

Was wenn ein Client mit zwei Servern kommuniziert: Einmal mit Verschlüsselung und einmal ohne? Werde mal schauen ob ich nicht das Setzen der CustomEncryption auf Registry und Lookup verlagere um so für eine einzelne Verbindung entscheiden zu können oder verschlüsselt wird oder nicht.

Was sagst du prinzipiell dazu?

Gruß
Alex

P.S. Mit dem letzten Redmine-Update ist wohl der Java-Code-Formatierungsknopf abhanden gekommen. Mal schauen dass ich den wieder einbaue ...

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Hab meine Änderungen mal eingecheckt: http://dev.root1.de/projects/simon/repository/diff?utf8=%E2%9C%93&rev_to=642&rev=641

Die Methoden zum setzen der Custom-Encryption sind nun im Lookup und in der Registry Klasse zu finden.

Werden die Tage dann mal das Jasyp Projekt für SIMON anlegen und in den automatischen Build einbauen. Bis dahin kannst du ja den oben geposteten Mehrzeiler verwenden.

Gruß
Alex

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Was mir gerade so noch einfällt:

Eine Fehlerbehandlung wird so einfach nicht möglich sein. Die Verschlüsselung setzt außerhalb des SIMON-Protokolls an. Wenn etwas nicht passt, dann fliegt unter Umständen eine RuntimeException mit mehr oder weniger cryptischem Inhalt. Passt das PW eines Clients nicht zu dem des Servers, so fliegt auf dem Server eine Jasypt-relevante Exception die besagt: Konnte nicht entschlüsseln. Wieso und warum verschweigt Jasypt aus Prinzip. Am Client sieht man nur, dass die Session geschlossen wurde. Mehr nicht. Mehr ist da an der Stelle auch nicht möglich.

Gruß
Alex

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by timekeeper about 5 years ago

Hallo Alex,

Ich fürchte, dass Du Dir das etwas zu einfach vorstellst.

Asymmetrische Verschlüsselung bedeutet, dass der Empfänger ein Schlüsselpaar (einen privaten zum Entschlüssel und einen öffentlichen zum Verschlüsseln) erzeugt und dem Sender den öffentlichen Schlüssel zukommen lässt. Dieser nutzt nun den öffentlichen Schlüssel zum Verschlüsseln seiner Nachricht, schickt ihn an den Empfänger und der Empfänger entschlüsselt mit dem privaten Schlüssel.

Das Ganze ist nur deswegen sicher, weil der private Schlüssel ausser dem Empfänger niemandem bekannt ist, er also auch nie über die Leitung gehen darf. Auch darf er nicht zum Verschlüsseln verwendet werden, weil das Gegenstück - der öffentliche Schlüssel - über die Leitung ging und damit von anderen mitgelesen werden kann.

Da nun bei SIMON sowohl der Client als auch der Server einen Datentransfer initiieren kann, benötigen beide den öffentlichen Schlüssel des anderen. Der Server könnte aus Vereinfachungsgründen für alle Clients dasselbe Schlüsselpaar verwenden.

Nichtsdestotrotz: Beim initialen Verbindungsaufbau müsste der Client seinen öffentlichen Schlüssel verschicken und in der Antwort (z.B. im Lookup) müsste der öffentliche Schlüssel des Servers zurückkommen.

Oder passiert das alles schon in Deinem Ansatz?

Hermann

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by timekeeper about 5 years ago

Nachdem nun letztendlich die Verwendung von TLS (bzw. SSL) so einfach ist, auch wenn man nur self signed certificates hat, benötige ich diese Erweiterung nicht mehr.

Man geht einfach folgendermaßen vor:

  1. Client-Zertifikat mit keytool erzeugen -> client keystore
  2. Server-Zertifikat mit keytool erzeugen -> server keystore
  3. Client-Zertifikat aus client keystore exportieren
  4. Client-Zertifikat in den server keystore importieren
  5. Server-Zertifikat aus server keystore exportieren
  6. Server-Zertifikat in den client keystore importieren

Die einzige Erweiterung, welche mit den Aufwand noch drastisch reduziert hätte, wäre ein Konstruktor der DefaultSslContextFactory, welcher einen InputStream akzeptiert, um den keystore direkt im Jar referenzieren zu können.

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

Hallo Hermann,

Ich fürchte, dass Du Dir das etwas zu einfach vorstellst.

Ich fürchte nicht.

Asymmetrische Verschlüsselung bedeutet, dass der Empfänger ein Schlüsselpaar (einen privaten zum Entschlüssel und einen öffentlichen zum Verschlüsseln) erzeugt und dem Sender den öffentlichen Schlüssel zukommen lässt. Dieser nutzt nun den öffentlichen Schlüssel zum Verschlüsseln seiner Nachricht, schickt ihn an den Empfänger und der Empfänger entschlüsselt mit dem privaten Schlüssel.

Korrekt. Aber wer sagt dass das "zukommen lassen" über die Anwendung selbst erfolgen muss? Würde hier immer einen separaten Weg wählen.

Da nun bei SIMON sowohl der Client als auch der Server einen Datentransfer initiieren kann, benötigen beide den öffentlichen Schlüssel des anderen.

Das gilt nur, wenn du tatsächlich zwei Verbindungen benutzt. Dran denken: SIMON baut eine Verbindung auf welche bidirektional ist. Also ist nur in eine Richtung ein öffentlicher Schlüssel von nöten.

Nichtsdestotrotz: Beim initialen Verbindungsaufbau müsste der Client seinen öffentlichen Schlüssel verschicken und in der Antwort (z.B. im Lookup) müsste der öffentliche Schlüssel des Servers zurückkommen.

Das verschicken öffentlicher Schlüssel macht doch nur dann Sinn, wenn immer mal wieder wechselnde/neue Partner hinzukommen. Wenn der Server lauter bekannte Clienbts hat, dann kann man einmal bei der Installation des Clients den Schlüssel angeben und fertig. Das muss nicht zwingend über eine Client-Server Kommunikation stattfinden. Der Serverbetreiber kann dem Client-Benutzer auch eine Schlüsseldatei zur Verfügung stellen (per Email, USB-Stick, ausgedruckt per Post joke, ...), welche der Benutzer dann im Client, ähnlich wie das eingeben eines Passworts angibt. Fertig.

Nachdem nun letztendlich die Verwendung von TLS (bzw. SSL) so einfach ist, auch wenn man nur self signed certificates hat, benötige ich diese Erweiterung nicht mehr.

Wie wenn ich es gewusst hätte. SSL ist einfach, wenn man die paar Grundlegenden Basics beherrscht ;-)

Gruß
Alex

RE: Verschlüsselung der Datenübertragung ohne den Aufwand von SSL-Zertifikaten - Added by achristian about 5 years ago

So, wie bereits geschrieben, das Feature wird nicht mehr gestrichen.. Es ist fertig:

Siehe #168

Verwendung mit Simon:

http://dev.root1.de/project-sites/simon/apidocs/de/root1/simon/Lookup.html#setCustomEncryption(de.root1.simon.CustomEncryption)
http://dev.root1.de/project-sites/simon/apidocs/de/root1/simon/Registry.html#setCustomEncryption(de.root1.simon.CustomEncryption)

Um eine eigene Verschlüsselung zu verwenden, einfach dieses Interface implementieren und eine je eine Instanz davon dem Lookup und der Registry geben:

http://dev.root1.de/project-sites/simon/apidocs/de/root1/simon/CustomEncryption.html

Eine Beispiel-Implementierung basierend auf Jasypt und Password-based-Encryption findet man hier:

http://dev.root1.de/projects/simon/repository/show/trunk/simon-jasypt

Und CI Server baut das Teil auch schon mit: http://jenkins.root1.de/job/Jasypt%20for%20SIMON%20-%20trunk/

Maven Dependency:

<dependency>
  <groupId>de.root1</groupId>
  <artifactId>simon-jasypt</artifactId>
  <version>1.0.0</version>
</dependency>

Zu finden in eigenen Maven Repo: http://nexus.root1.de/content/repositories/releases/

Aber ACHTUNG:

Mit der neuen 1.2.0-SNAPSHOT muss nun ab sofort die Registry via "start()" selbst gestartet werden. Das wurde nötig um die Registry zuvor noch "konfigurieren" zu können (bzw. im speziellen hier: Verschlüsselung setzten).

Gruß
Alex

(1-10/10)