Delphi-PRAXiS
Seite 3 von 6     123 45     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy & OpenSSL 1.1.1 & TLS 1.3 (https://www.delphipraxis.net/204185-indy-openssl-1-1-1-tls-1-3-a.html)

Kostas 5. Jul 2020 09:56

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Oh, ich glaube ich habe es "fast" geschafft.

Ich bin so vorgegangen:
- /Lib/Fullc_Rio.bat ausgeführt, am Ende ist der Hinweis erschienen: keine Fehler.
- Öffne IndySystem260.dpk, natürlich jede Menge Fehler Package kann nicht geladen werden. Beim nächsten Start neu laden alles mit Ja bestätigt.
IndySystem260.dpk konnte ohne Fehler erzeugt werden.
- dclIndyCore260.dpk wollte ich erzeugen und bekommen die Meldung IndyCore260.res nicht gefunden. Die Datei gibt es unter
\Indy-NewOpenSSL_PR\C26\Win32\Release. Der Order \C26\ wurde durch die .bat erzeugt. Ich habe den Pfad in die Bibliothek aufgenommen und konnte dann Fehlerfrei erzeugen.
- dclIndyProtocols260.dpk Fehlerfrei erzeugen und installieren können.
- dclIndyCore260.dpk Fehlerfrei erzeugen und installieren können.
- dclIndyProtocols260.dpk Fehlerfrei erzeugen und installieren können.
- Delphi neu gestartet und bekomme keine Fehler mehr. Scheint soweit funktioniert zu haben.

Deine zusätzlichen SSLIOHandler finde ich nicht. Wie muss ich diese bitte installieren?

mezen 5. Jul 2020 11:08

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Für die IO Handler gibt es noch keine Design Time Komponenten. Einfach mit ins uses aufnehmen, und selber instantiieren.

Kostas 5. Jul 2020 11:37

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
auf die Gefahr hin dass du mich jetzt steinigst,
auf meine Form habe ich ein TIdHTTP und ein TIdSSLIOHandlerSocketOpenSSL.
Ich nehme an, ich muss nur IdHTTP.IOHandler abhängen von IdSSLIOHandlerSocketOpenSSL und dafür deine Variante einbinden.
Welche Unit sollte ich dafür usen und welche Komponenten müsste ich bitte instantiieren und dem IdHTTP.IOHandler zuweisen?
Die DLLs libssl-1_1-x64.dll und libcrypto-1_1-x64.dll habe ich bereits von ICS abgerufen und in Programm Root kopiert.

mezen 5. Jul 2020 13:15

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Aus der IdOpenSSLIOHandlerClient.pas den TIdOpenSSLIOHandlerClient für Clients, bzw aus der IdOpenSSLIOHandlerServer.pas den TIdOpenSSLIOHandlerServer für Server.

Kostas 5. Jul 2020 14:52

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hast du mir bitte noch ein Hinweis was ich alles in dem Bibliothekspfad aufnehmen muss, es hört gar nicht auf, da stimmt etwas nicht.
C:\Komponenten\Indy-NewOpenSSL_PR\C26\Win32\Release
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols
...

Aktuell wird TIdLibHandle in IdSSLOpenSSLHeaders vermisst.

mezen 6. Jul 2020 16:07

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Für meine Änderungen sind nur folgende Pfade notwendig:

C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL\dynamic bzw C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL\static je nachdem ob du mit dynamischen Laden der DLL (
Delphi-Quellcode:
LoadLibrary
etc) oder statischem Linken gegen die DLLs (
Delphi-Quellcode:
procedure Foo; external 'MyDll.dll';
) arbeitest.

Indy hat dafür die Compiler Directive STATICLOAD_OPENSSL. Wenn ich mich richtig erinnere, ist dies etwas was bei der Installation von Indy bestimmt wurde. Du kannst beispielhaft mal in IdOpenSSLLoader.pas gucken, ohne STATICLOAD_OPENSSL ist die Unit quasi leer.

Die restlichen Pfade haben mit der Indy Installation zu tun und sich unabhängig von meinen Änderungen.

Kostas 6. Jul 2020 17:11

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Ich habe in den Bibliothekspfad von Delphi alle Pfade gelöscht und folgende hinzugefügt:
Delphi-Quellcode:
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL\dynamic
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols\OpenSSL\static
Da ich nicht weis was verwendet wird habe ich dynamic und static aufgenommen.
In meiner Form unter uses habe ich IdOpenSSLLoader aufgenommen und mit Strg+Enter die Datei geöffnet. Sie ist nicht leer und hat 349 Zeilen.

Auf der Form habe ich eine TIdHTTP Komponente.
Delphi-Quellcode:
uses IdOpenSSLIOHandlerClient, IdOpenSSLLoader;

//das wollte ich ausführen.
procedure TfrMain.Button1Click(Sender: TObject);
var IdOpenSSLIOHandlerClient :TIdOpenSSLIOHandlerClient;
begin
  IdOpenSSLIOHandlerClient.Create;
  try
    IdOpenSSLIOHandlerClient.SSLOptions.Method := sslvTLSv1_3;
    IdHTTP1.IOHandler := IdOpenSSLIOHandlerClient;
    LoadHistoryFile(ed.Text);
  finally
    IdHTTP1.IOHandler := nil;
    IdOpenSSLIOHandlerClient.Free;
  end;
end;
Wenn ich so versuche zu kompilieren, wird die Datei IdOpenSSLIOHandlerClient geöffnet und {$i IdCompilerDefines.inc} wurde nicht gefunden angezeigt.
Ich habe danach gesucht und gefunden unter:
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\System
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\SuperCode
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\FCL
C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Core

also habe ich C:\Komponenten\Indy-NewOpenSSL_PR\Lib\Protocols in den Bibliothekspfad aufgenommen und neu kompiliert. Dann bleibt er stehen bei
IdSSLOpenSSLHeaders und vermisst TIdLibHandle;

dschiffler 28. Nov 2020 11:36

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hallo mezen,

erst einmal auch von mir ein großes Danke schön und Respekt für deine Arbeit.
Hoffentlich fließt deine Arbeit irgenwann auch in die Indy-Version von Delphi ein. :-D

Nun zu meinem Problem:
Ich habe eine Software die sich per SSL/TLS mit einem Webserver verbindet, den wir selbst in der Verwaltung haben. Auf dem Webserver ist ein Zertifikat installiert. Beim Verbindungsaufbau zum Webserver überprüft die Software den Fingerprint des Server-Zertifikats, um sicherzustellen, dass die Verbindung zum richtigen Webserver erfolgt.
Umgesetzt ist dies mit Indy 10 von Delphi 10.3 und funktioniert einwandfrei.

Hier der relevante Code-Ausschnitt dazu (FHttpClient ist eine Instanz von TIdHttp):
Delphi-Quellcode:
var
  lHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
  FHttpClient.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(FHttpClient);

  lHandler := TIdSSLIOHandlerSocketOpenSSL(FHttpClient.IOHandler);
  lHandler.SSLOptions.Mode := sslmClient;
  lHandler.SSLOptions.VerifyMode := [sslvrfPeer];
  lHandler.OnVerifyPeer := DoVerifyPeer;
end;
Die Signatur von DoVerifyPeer ist folgende:
Code:
function DoVerifyPeer(ACertificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
Mit dem Parameter ACertificate bekommt man Zugriff auf die Zertifikat-Informationen/-Eigenschaften und ich kann in DoVerifyPeer dann folgendes machen:
Delphi-Quellcode:
var
  sFingerprint: string
begin
  sFingerprint := ACertificate.Fingerprints.SHA1AsString;
  Result := <Vergleich mit dem erwarteten Fingerprint>
end
Im Getter von SHA1AsString wird folgendes aufgerufen:
Code:
Result := MDAsString(SHA1);
In der Funktion MDAsString wird lediglich die Rückgabe von SHA1 als Hex-Zahlen mit Doppelpunkt getrennt formatiert (was nicht weiter wichtig ist), denn das Entscheidende passiert in der Funktion SHA1, nämlich der Aufuf von X509_digest, was ja eine Funktion aus den OpenSSL-DLLs ist:
Delphi-Quellcode:
begin
  X509_digest(FX509, EVP_sha1, PByte(@Result.MD), Result.Length);
end

Wenn ich jetzt deinen OpenSSL-Client benutze (damit ich auch TLS 1.3 unterstützen kann), sieht die Implementierung so aus:
Delphi-Quellcode:
var
  lHandler: TIdOpenSSLIOHandlerClient;
begin
  FHttpClient.IOHandler := TIdOpenSSLIOHandlerClient.Create(FHttpClient);

  lHandler := TIdOpenSSLIOHandlerClient(FHttpClient.IOHandler);
  lHandler.Options.CipherList  := IdOpenSSLHeaders_ssl.SSL_DEFAULT_CIPHER_LIST;
  lHandler.Options.CipherSuites := IdOpenSSLHeaders_ssl.TLS_DEFAULT_CIPHERSUITES;
  lHandler.Options.UseServerCipherPreferences := False;
  lHandler.Options.VerifyServerCertificate := True;
  lHandler.Options.OnVerify := DoVerifyPeer;
end;
Die Signatur von DoVerifyPeer ist hier folgende:
Code:
procedure DoVerifyPeer(ASender: TObject; const ACertificate: TIdOpenSSLX509;
  const VerifyResult, Depth: Integer; var Accepted: Boolean);
Auch hier kann ich mit dem Parameter ACertificate auf die Zertifikat-Informationen/-Eigenschaften zugreifen und in DoVerifyPeer dann folgendes machen:
Delphi-Quellcode:
var
  sFingerprint: string
begin
  sFingerprint := ACertificate.ThumbprintAsSHA1;
  Accepted := <Vergleich mit dem erwarteten Fingerprint>
end
Im Getter von ThumbprintAsSHA1 wird folgndes aufgerufen:
Code:
Result := GetInternalThumbprint(EVP_sha1());
Das Entscheidende hier ist auch der Aufruf der Funktion X509_digest in der Methode GetInternalThumbprint:
Delphi-Quellcode:
var
  LBuffer: array[0 .. EVP_MAX_MD_SIZE -1] of Byte;
  LByteCount: TIdC_UINT;
  i: Integer;
begin
  Result := '';
  LByteCount := EVP_MAX_MD_SIZE;
  if X509_digest(FX509, md, @LBuffer, @LByteCount) = 1 then
  begin
    for i := 0 to LByteCount - 1 do
      Result := Result + ByteToHex(LBuffer[i]);
  end;
end;
Nach meinem Verständnis sollte doch hier die gleiche Bytefolge (also der Fingerprint des Server-Zertifikats) zurückkommen?
Das passiert aber nicht, denn die Bytefolge ist eine vollkommen andere.

Habe ich bei der Konfiguration des IO-Handlers etwas falsch gemacht oder vergessen oder wo liegt der Fehler?
Ich hoffe, dass der Fehler nicht in den OpenSSL-DLLs liegt?

mezen 28. Nov 2020 12:26

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Es sollte das selbe rauskommen. Ich kann das leider erst am Dienstag in der Firma mir detaillierter anschauen. Bei meinen Tests kam damals da aber der selbe SHA1 Wert raus als wenn ich mir das Zert direkt angeschaut habe.

Bedenke aber bitte, dass das OnVerifyPeer pro Zertifikat aufgerufen wird, welches der Server zurück schickt. Sollte der Server mehrere zurückschicken (z.B. sein Server Zert plus ein Intermediate Zert), dann wird die Funktion mehrmals aufgerufen.

Wenn dir das erwartete Zertifikat aber bekannt ist, gib es besser direkt als Datei an, anstatt im OnVerifyPeer den Thumbprint zu vergleichen.
Überlass damit besser die Zertifikats Validierung komplett OpenSSL, da genug Leute sagen, dass der gefährlichste selbst geschriebene Code eine eigene Zertifikats Validierung ist.

dschiffler 29. Nov 2020 20:12

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hallo mezen,

danke für deine Antwort. Dann warte ich, bis du deine Überprüfung abgeschlossen hast. :-D

Zu deinen Bemerkungen:
Das Ereignis OnVerifyPeer wird in meinem Fall nur einmal aufgerufen, denn auf dem Webserver ist definitiv nur ein Zertifikat installiert. Wie gesagt, mit Indy 10 unter Delphi 10.3.x läuft ja alles wunschgemäß. Wenn ich jetzt also lediglich den SSL-IO-Handler von Indy auf deinen wechsle und anschließend kommt eine andere Bytefolge als Fingerprint zurück, liegt ja zumindest der Verdacht nahe, dass entweder in deinen Implementierungen oder aber in den neuen SSL-Bibliotheken etwas anders als in den Indy-Komponenten und den bisherigen SSL-Bibliotheken ist.

Dein Hinweis, die Überpüfung des Zertifikats OpenSSL zu überlassen, ist interessant.
In deinen SSL-Options gibt es ja die Properties CertFile und CertKey. Laut deiner Doku dazu muss hier ein Verzeichnis angegeben werden, in dem sogenannte pem-Dateien liegen müssen.
Dazu 3 Fragen:
  • Müssen beide Properties gesetzt sein oder reicht CertFile?
  • Wo bzw. von wem bekomme ich denn diese pem-Dateien und was beinhalten diese?
  • Wie läuft denn dann die Validierung des Zertifikats ab oder besser gesagt, wie bekomme ich die Info, ob die Validierung erfolgreich war oder nicht, so dass ich darauf entspr. reagieren kann?


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:48 Uhr.
Seite 3 von 6     123 45     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz