Laden...

Privaten Schlüssel zur Signierung in MessageSignature verwenden

Erstellt von TiloS vor 5 Jahren Letzter Beitrag vor 5 Jahren 2.247 Views
T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren
Privaten Schlüssel zur Signierung in MessageSignature verwenden

Hallo,

ich versuche ein Request eines SoapClient-Objekts mit Hilfe eines MessageSignatur-Objekts mit meinem privaten Schlüssel zu signieren. Der private Schlüssel liegt als String "MIIE6jAc..." oder als .pkcs8-Datei vor.
Das MessageSignatur-Objekt hat einen SecurityToken, in den das X509Zertifikat (öffentlicher Schlüssel) als Token gehört, das sollte passen. Die Signatur-Referenzen habe ich angegeben. Weiterhin hat das Objekt einen SigningToken und einen SigningKey, der meiner Auffassung nach für den privaten Schlüssel vorgesehen ist. Damit sollten die entsprechenden Teile des Requests signiert werden.

Wie mache ich aus dem privaten Schlüssel einen SigningToken oder einen SigningKey? Ich habe dazu leider noch nichts konkretes gefunden.

Den privaten Token wie den öffentlichen Token über ein Microsoft.Web.Services2.Security.X509.X509Certificate zu erstellen, funktioniert nicht. Das ist wohl auch nicht so vorgesehen.


    messageSignature.SigningToken = privateKeyToken;
    //messageSignature.SigningKey =

Hat jemand dazu eine Idee?

Gruß
Tilo

T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren

Ich habe noch einen Tipp bekommen, den Private Key evtl. im RSA-Format zu nutzen. Mit OpenSSL habe ich mir den in RSA-XML umgewandelt und versuche ihn mit dem RSACryptoServiceProvider zu nutzen. Das sieht dann so aus:


    string privatekey_rsa_format = "<RSAKeyValue><Modulus>00G2um/iUiNip…";
    RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
    rsaCryptoServiceProvider.FromXmlString(privatekey_rsa_format);

Den bekomme ich allerdings nicht in das MessageSignatur-Objekt. Die Zuweisung ist nicht möglich:


    messageSignature.SigningKey = rsaCryptoServiceProvider;

Auch der Umweg über X509Certificate2, bei dem man an das Zertifikat (public key) den PrivateKey mitgeben kann, funktioniert nicht.

Es sieht so aus, als könnte man die Typen nicht ineinander umwandeln. Falls doch wäre ich für jede Hilfe dankbar.

Ich denke, das MessageSignatur-Objekt ist genau für solche Sachen da, also um ein Request mit der Angabe von

  •   dem öffentlichen Schlüssel (als SecurityToken)  
    
  • den Referenzen der zu signierenden Teile und
  • dem privaten Schlüssel mit dem das Objekt die entsprechenden Teile signieren soll
    zu signieren.

Dann muss es doch auch damit möglich sein. Gibt es da eine Möglichkeit?

Gruß
Tilo

16.828 Beiträge seit 2008
vor 5 Jahren
messageSignature.SigningKey = rsaCryptoServiceProvider;

Damit versuchst Du einem Token einen Provider zuzuweisen. Das kann ja nicht gehen.
Du kannst auch kein LKW in ein PKW-Parkplatz parken. Macht ja auch kein Sinn.

Mich würde hier wundern, wenn der SoapClient was anderes wollen würde als ein X509 Certificate

T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren

So unterschiedlich sind m.E. die Typen gar nicht. Der Provider ist auch eine Art Key, er lässt sich z.B. dem PrivateKey des X509Certificate2-Zertifikat zuweisen:


    X509Certificate2 cert2 = new X509Certificate2(certByte);
    cert2.PrivateKey = rsaCryptoServiceProvider;

Das geht.
Der cert2.PrivateKey ist allerdings ein anderer Typ als der SigningKey:
System.Security.Cryptography.AsymetricAlgorithm
vs.
Microsoft.Web.Services2.Security.Security.Cryptography.KeyAlgorithm

Aber Du hast recht, ein X509 Zertifikat aktzeptiert er. Und der SoapClient bekommt natürlich auch ein X509 Zertifikat. Das ist aber der öffentliche Schlüssel, und den hat er schon.
Vielleicht habe ich noch ein Verständnisproblem.

Es geht ja zuerst mal um das MessageSignatur-Objekt, das brauche ich ja für die Signierung. Und für die Signierung brauche ich den privaten Schlüssel. Die erzeugte Signatur würde ich dann in das Request des SoapClient einfügen.
Dem MessageSignatur-Objekt kann ich nebenbei auch noch einen SecurityToken (öff. Schlüssel) mitgeben, aber ich muss ja irgendwo auch den privaten Schlüssel mitgeben, mit dem das MessageSignatur-Objekt die Teile signieren soll.
Oder sehe ich das nicht richtig?

16.828 Beiträge seit 2008
vor 5 Jahren

So unterschiedlich sind m.E. die Typen gar nicht.

Die Typen sind Welt-Verschieden; nur die Namen klingen ähnlich.
Das eine ist ein Token, das andere ein Verschlüsselungsalgorithmus und deswegen kann dem auch ein Provider zugewiesen werden (da in diesem der Algorithmus steckt).

X509Certificate alleine sagt ja nicht aus, welcher Key drin steckt. Kann ja Public und Private sein.
Ich vermute, dass Du der MessageSignatur Instanz eben ein X509 Private geben musst.
Würde jedenfalls Sinn machen.

T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren

Vielen Dank bis hierher.

Hier ist mal mein Code, damit man sieht, was ich wie vorhabe. Evtl. kann ich das je grundsätzlich so nicht machen?


        //unsigniertes Request
        string request = "<?xml version='1.0' encoding='UTF-8'?>...";

        //SoapClient-Klasse nutzen
        EndpointReference destination = new EndpointReference(uri);
        TcpClient tokenservice = new TcpClient(destination);

        //Request in SoapEnvelope einlesen
        SoapEnvelope envelope = new SoapEnvelope();
        envelope.LoadXml(request);

        //Token erzeugen (public key)
        Microsoft.Web.Services2.Security.X509.X509Certificate certX509 = new Microsoft.Web.Services2.Security.X509.X509Certificate(certByte);
        Microsoft.Web.Services2.Security.Tokens.SecurityToken certToken = new Microsoft.Web.Services2.Security.Tokens.X509SecurityToken(certX509);
        certToken.Id = "b";

        //MessageSignature-Objekt erzeugen
        MessageSignature messageSignature = new MessageSignature(certToken);        //oder XmlDocument?
        messageSignature.Document = envelope;

        //private key
        String privatekey_rsa_format = "<RSAKeyValue><Modulus>00G2um/iUiNi...";
        RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
        rsaCryptoServiceProvider.FromXmlString(privatekey_rsa_format);

        //Zuweisung des private key zum MessageSignatur-Objekt
        messageSignature.SigningKey = ?
        //oder
        messageSignature.SigningToken = ?

        //zu signierende Teile referenzieren und Signierung durchführen
        SignatureReference soapRef1 = new SignatureReference("#t");
        soapRef1.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        SignatureReference soapRef2 = new SignatureReference("#b");
        soapRef2.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        SignatureReference soapRef3 = new SignatureReference("#n");
        soapRef3.AddTransform(new Microsoft.Web.Services2.Security.Xml.XmlDsigExcC14NTransform());

        messageSignature.AddReference(soapRef1);
        messageSignature.AddReference(soapRef2);
        messageSignature.AddReference(soapRef3);

        messageSignature.ComputeSignature();

        //to do: Signatur in das Request einbauen

        //Request absenden
        SoapEnvelope returnEnvelope = tokenservice.RequestResponseMethod(envelope);

T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren

Ich versuche jetzt das Zertifikat (inklusive dem privaten Schlüssel) aus dem Keystore zu lesen und dann mit WSE 3.0-Objekten (anstatt WSE 2.0) weiter zu machen. Das verspricht mehr Erfolg. Vorallem, weil ich dabei direkt das X509Certificate2 (was den privaten Schlüssel beinhaltet) nutzen kann.

Nun wirft mir aber das Erzeugen des X509Certificate2 einen merkwürdigen Fehler auf, und zwar:> Fehlermeldung:

System.Security.Cryptography.CryptographicException: "Das angeforderte Objekt wurde nicht gefunden."

Mein Code dazu:


    string pfxFilename = @"C:\Cert\keystore.pfx";
    string pfxAndCertPassword = "pass";

    X509Certificate2 certFromKeystore = new X509Certificate2(pfxFilename, pfxAndCertPassword);

Es ist nicht so, dass die Datei nicht gefunden wird. Das würde eine andere Fehlermeldung liefern (getestet), sondern irgend ein Objekt wird nicht gefunden.

In dem keystore.pfx sind auch korrekte und gültige Daten enthalten. Im SoapUI-Testcase bin ich damit erfolgreich.

Hat jemand dazu eine Idee?

16.828 Beiträge seit 2008
vor 5 Jahren

Wäre nun von Vorteil, wenn Du englische Fehlermeldungen hättest - damit könnte man vermutlich mehr anfangen als mit dem lokalisierten Käse 😉

T
TiloS Themenstarter:in
35 Beiträge seit 2012
vor 5 Jahren

Die Fehlermeldung lautet: > Fehlermeldung:

"Cannot find the requested object"

Auch das Einlesen in eine Collection bringt den selben Fehler.


    X509Certificate2Collection collection = new X509Certificate2Collection();
    collection.Import(pfxFilename, pfxAndCertPassword, X509KeyStorageFlags.PersistKeySet);