E2EE (End-To-End Encryption) for Delphi

· Components

Ab Version 2026.1.0 wird E2EE (End-to-End-Verschlüsselung) unterstützt (nur für eSeGeCe All-Access-Abonnenten).

End-to-End-Verschlüsselung (E2EE) stellt sicher, dass nur die kommunizierenden Peers den Inhalt der ausgetauschten Nachrichten lesen können. Selbst der Server, der die Nachrichten weiterleitet, kann sie nicht entschlüsseln. Dieser Artikel erklärt, wie E2EE zwischen zwei Peers mithilfe von Public-Key-Kryptografie funktioniert, um Nachrichten sicher auszutauschen.

E2EE erklärt

Grundprinzipien von E2EE

In einem E2EE-System mit zwei Peers:


Überblick über das Schlüsselmaterial

Jeder Peer (zum Beispiel Alice und Bob) besitzt:

Öffentliche und private Schlüssel sind mathematisch miteinander verknüpft, doch aus dem öffentlichen Schlüssel lässt sich der private Schlüssel nicht ableiten.


Schritt 1: Austausch der öffentlichen Schlüssel

Bevor verschlüsselte Kommunikation stattfinden kann, müssen Alice und Bob die öffentlichen Schlüssel des jeweils anderen kennen.

Typische Vorgehensweisen:

Dieser Austausch beeinträchtigt die Sicherheit nicht, da öffentliche Schlüssel nicht geheim sind.


Schritt 2: Etablieren eines gemeinsamen Geheimnisses (ECDH)

Um Nachrichten effizient zu verschlüsseln, leiten Alice und Bob zunächst ein gemeinsames Geheimnis mit Elliptic Curve Diffie–Hellman (ECDH) ab.

So funktioniert ECDH konzeptionell

Aufgrund der mathematischen Eigenschaften elliptischer Kurven liefern beide Berechnungen denselben geheimen Wert, obwohl keine Seite dieses Geheimnis je überträgt.

Zu keinem Zeitpunkt wird das gemeinsame Geheimnis über das Netzwerk gesendet.


Schritt 3: Ableitung eines symmetrischen Verschlüsselungsschlüssels

Das rohe ECDH-Geheimnis wird nicht direkt zur Verschlüsselung verwendet. Stattdessen wird es durch eine Key Derivation Function (KDF) verarbeitet, typischerweise einen kryptografischen Hash wie SHA-256.

Zweck der Schlüsselableitung:


Das Ergebnis ist ein symmetrischer Verschlüsselungsschlüssel, der nur Alice und Bob bekannt ist.


Schritt 4: Verschlüsseln der Nachricht

Wenn Alice eine Nachricht an Bob senden möchte:

  1. Alice wandelt die Nachricht in Bytes um.
  2. Alice verschlüsselt die Nachricht mit einem symmetrischen Verfahren (üblicherweise AES-GCM) und verwendet dabei:
    • Den abgeleiteten symmetrischen Schlüssel
    • Einen zufälligen Initialisierungsvektor (IV)
  3. Alice sendet die verschlüsselte Nachricht und den IV über den Server an Bob.

AES-GCM wird häufig eingesetzt, weil es bietet:



Schritt 5: Entschlüsseln der Nachricht

Wenn Bob die verschlüsselte Nachricht empfängt:

  1. Bob leitet unabhängig denselben symmetrischen Schlüssel mit ECDH und derselben KDF ab.
  2. Bob entschlüsselt die Nachricht mit dem symmetrischen Schlüssel und dem IV.
  3. Ist die Authentifizierung erfolgreich, erhält Bob den ursprünglichen Klartext.

Wurde die Nachricht verändert oder ein falscher Schlüssel verwendet, schlägt die Entschlüsselung fehl.


Rolle des Servers

In dieser Architektur tut der Server:


Der Server kann nicht:


Das ist die definierende Eigenschaft von End-to-End-Verschlüsselung.


Zusammenfassung

End-to-End-Verschlüsselung zwischen zwei Peers funktioniert durch die Kombination von:

  1. Public-Key-Kryptografie (für die Schlüsselvereinbarung)
  2. Symmetrische Kryptografie (für effiziente Nachrichtenverschlüsselung)
  3. Key Derivation Functions (für Sicherheit und Korrektheit)

Das Ergebnis ist ein System, in dem:


Dieses Modell ist das kryptografische Rückgrat moderner sicherer Messaging-Systeme. 

E2EE-Beispiel

// ... Create the Server
WSServer := TsgcWebSocketHTTPServer.Create(nil);
WSServer.Port := 80;
WSPE2EE := TsgcWSPServer_E2EE.Create(nil);
WSPE2EE.Server := WSServer;
WSServer.Active := True;
// ... Create 2 clients
WSClient1 := TsgcWebSocketClient.Create(nil);
WSClient1.Host := '127.0.0.1';
WSClient1.Port := 80;
E2EE1 := TsgcWSPClient_E2EE.Create(nil);
E2EE1.Client := WSClient1;
E2EE1.E2EE_Otpions.UserId := 'client-1';
WSClient1.Active := True;
WSClient2 := TsgcWebSocketClient.Create(nil);
WSClient2.Host := '127.0.0.1';
WSClient2.Port := 80;
E2EE2 := TsgcWSPClient_E2EE.Create(nil);
E2EE2.OnE2EEMessageText := OnE2EEMessageTextEvent;
E2EE2.E2EE_Otpions.UserId := 'client-2';
E2EE2.Client := WSClient2;
WSClient2.Active := True;
// ... client-1 send a message to client-2
E2EE1.SendDirectMessage('client-2', 'Hello Client-2');
// ... read the message in the OnE2EEMessageText event
procedure OnE2EEMessageText(Sender: TObject; const aFrom, aText: string);
begin
  DoLog('#direct_message: ' + aText);
end;