Frage

Ich dachte, das einfach sein würde, aber anscheinend ist es nicht. Ich habe ein Zertifikat installiert, die einen privaten Schlüssel hat, exportierbar, und ich möchte es programmatisch nur mit dem öffentlichen Schlüssel exportieren. Mit anderen Worten, ich möchte ein Ergebnis entspricht der Auswahl von „Setzen Sie den privaten Schlüssel nicht exportieren“, wenn durch CertMgr Export und den Export in .CER.

Es scheint, dass alle der X509Certificate2.Export Methoden, um die privaten Schlüssel exportieren, wenn es vorhanden ist, wie PKCS # 12, das ist das Gegenteil von dem, was ich will.

Gibt es eine Möglichkeit mit C #, dies zu erreichen, oder muss ich Graben in CAPICOM starten?

War es hilfreich?

Lösung

Für alle anderen, die auf diese gestoßen haben könnte, dachte ich es aus. Wenn Sie X509ContentType.Cert als die ersten (und einzigen) Parameter angeben, um zu X509Certificate.Export, exportiert es nur den öffentlichen Schlüssel. Auf der anderen Seite, X509ContentType.Pfx Angabe enthält den privaten Schlüssel, falls vorhanden.

Ich hätte schwören können, dass ich ein anderes Verhalten der vergangenen Woche war zu sehen, aber ich muss schon der private Schlüssel installiert, wenn ich Tests war. Als ich das Zertifikat heute gelöscht und begann wieder von vorne, sah ich, dass es in der exportierten cert keine privaten Schlüssel war.

Andere Tipps

Ich fand das folgende Programm hilfreich für mich beruhigend, dass die RawData Eigenschaft des Zertifikats nur der öffentliche Schlüssel enthält (MSDN ist unklar, auf dieser), und dass die Antwort oben in Bezug auf X509ContentType.Cert vs. X509ContentType.Pfx wie erwartet funktioniert:

using System;
using System.Linq;
using System.IdentityModel.Tokens;
using System.Security.Cryptography.X509Certificates;

class Program
{
    static void Main( string[] args )
    {
        var certPath = @"C:\blah\somecert.pfx";
        var certPassword = "somepassword";

        var orig = new X509Certificate2( certPath, certPassword, X509KeyStorageFlags.Exportable );
        Console.WriteLine( "Orig   : RawData.Length = {0}, HasPrivateKey = {1}", orig.RawData.Length, orig.HasPrivateKey );

        var certBytes = orig.Export( X509ContentType.Cert );
        var certA = new X509Certificate2( certBytes );
        Console.WriteLine( "cert A : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certA.RawData.Length, certA.HasPrivateKey, certBytes.Length );

        // NOTE that this the only place the byte count differs from the others
        certBytes = orig.Export( X509ContentType.Pfx );
        var certB = new X509Certificate2( certBytes );
        Console.WriteLine( "cert B : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certB.RawData.Length, certB.HasPrivateKey, certBytes.Length );

        var keyIdentifier = ( new X509SecurityToken( orig ) ).CreateKeyIdentifierClause<X509RawDataKeyIdentifierClause>();
        certBytes = keyIdentifier.GetX509RawData();
        var certC = new X509Certificate2( certBytes );
        Console.WriteLine( "cert C : RawData.Length = {0}, HasPrivateKey = {1}, certBytes.Length = {2}", certC.RawData.Length, certC.HasPrivateKey, certBytes.Length );

        Console.WriteLine( "RawData equals original RawData: {0}", certC.RawData.SequenceEqual( orig.RawData ) );

        Console.ReadLine();
    }
}

Es gibt folgende Möglichkeiten:

Orig   : RawData.Length = 1337, HasPrivateKey = True
cert A : RawData.Length = 1337, HasPrivateKey = False, certBytes.Length = 1337
cert B : RawData.Length = 1337, HasPrivateKey = True, certBytes.Length = 3187
cert C : RawData.Length = 1337, HasPrivateKey = False, certBytes.Length = 1337
RawData equals original RawData: True

Es gibt eine OpenSSL .NET-Wrapper Sie nützlich sein können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top