Thema: Delphi ASN.1 / DER dekodieren

Einzelnen Beitrag anzeigen

Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
652 Beiträge
 
Delphi 12 Athens
 
#2

AW: ASN.1 / DER dekodieren

  Alt 9. Apr 2021, 11:47
Ich bin über ein ähnliches Problem gestolpert, als ich neulich "JSON Web Keys" auswerten wollte, um mit diesen Zertifikaten dann wiederum ein Token zu verifizieren. Da kam auch etwas in diesem DER-Format vor. Mein Code hier wandelt dieses X509/DER-kodierte Gedöns in einen ganz "normalen" String im PEM-Format um. Dabei helfen die Indys insofern, weil sie halt die ganzen Befehle der OpenSSL-Bibliothek bereitstellen, d.h., die eigentliche Arbeit macht OpenSSL und dort findet man auch die Doku zu den ganzen nötigen Kommandos.

Hier also mein Code - ob er genau zu deinem Problem passt, kann ich nicht sagen, aber ich vermute, es wird zumindest einiges dabei sein, was in eine passende Richtung geht:

Delphi-Quellcode:
function TwebConfig.ConvertBaseX509ToPEM(aWebKey: string): string;

(* Wenn wir ein Zertifikat vom OAuth-Server als JSON Web Key abfragen, so ist das dort in einem etwas anstrengenden
  Format angegeben, dass wir nicht direkt verwenden können. Was wir wollen: ein ganz normales Zertifikat im gängingen
  PEM-Format. Was wir haben: Einen Base64-String, welcher das Zertifikat im Format X509 enthält und das wiederum
  im Format "DER" (irgendwas aus den Achtzigern...) kodiert. Wenn man ein paarmal den Kopf gegen die Wand gehauen
  hat, versteht man irgendwann, wie man die OpenSSL-Bibliothek nutzen kann, um zum gewünschten PEM-Format zu kommen.
*)


var
  byteArray: TBytes;
  bytePubKey: TBytes;
  certX509: PX509;
  bio: PBIO;
  PArray: Pointer;

begin
  if IdSSLOpenSSLHeaders.Load then begin
    try
      byteArray:=TNetEncoding.Base64.DecodeStringToBytes(aWebKey);
      // das Array und auch einen Pointer auf das Array dürfen wir an d2i_x509 nicht direkt übergeben, sondern müssen
      // ihn in eine andere Pointer-Variable kopieren, da d2i diesen Pointer nachher hinter das übergebene Byte-Array
      // zeigen lässt. Wir würden den Speichermanager zerschießen, wenn wir direkt das Array bzw. einen Pointer darauf übergeben.
      // Und ja: wir übergeben tatsächlich einen Pointer auf den Pointer - somit kann eben der eigentliche Pointer
      // geändert werden (letztlich wird so also ein "var-Parameter" realisiert.
      PArray:=@byteArray[0];
      certX509:=d2i_X509(nil,@PArray,length(byteArray));
      if certX509<>nil then begin
        bio:=BIO_new(BIO_s_mem);
        PEM_write_bio_X509(bio,certX509);
        SetLength(bytePubKey,bio.num_write);
        BIO_read(bio,bytePubKey,BIo.num_write);
        Result:=string(PAnsiChar(@bytePubKey[0]));
        BIO_free(bio);
        X509_free(certX509);
        SetLength(bytePubKey,0);
      end else
        Result:='';
    except
      on e: exception do begin
        Result:='';
        fLastError:=_('Fehler bei der Verarbeitung des Öffentlichen Schlüssels aus dem JSON Web Key.')+' '+_('Fehlermeldung:')+' '+e.Message;
      end;
    end;
    SetLength(byteArray,0);
  end;
end;
  Mit Zitat antworten Zitat