Domanda

Ho pensato che questo sarebbe stato semplice, ma a quanto pare non lo è. Ho un certificato installato che dispone di una chiave privata, esportabile, e voglio esportare a livello di codice con la chiave pubblica SOLTANTO. In altre parole, voglio un risultato equivalente a selezionare "Non esportare la chiave privata" durante l'esportazione attraverso CertMgr e l'esportazione in .CER.

Sembra che tutti i metodi X509Certificate2.Export esportare la chiave privata se esiste, come PKCS # 12, che è l'opposto di ciò che voglio.

C'è un modo utilizzando C # per raggiungere questo obiettivo, o ho bisogno di iniziare a scavare in CAPICOM?

È stato utile?

Soluzione

Per chiunque altro che potrebbe aver inciampato su questo, ho capito. Se si specifica X509ContentType.Cert come primo parametro (e unico) per X509Certificate.Export, esporta solo la chiave pubblica. D'altra parte, specificando X509ContentType.Pfx include la chiave privata se ne esiste uno.

avrei giurato che stavo vedendo un comportamento diverso la scorsa settimana, ma devo avere già aveva la chiave privata installata quando ero test. Quando ho cancellato quel certificato oggi e ha iniziato di nuovo da zero, ho visto che non vi era alcuna chiave privata nel cert esportato.

Altri suggerimenti

ho trovato il seguente programma utile per rassicurare me stesso che la proprietà RawData del certificato contiene solo la chiave pubblica (MSDN non è chiaro su questo), e che la risposta di cui sopra per quanto riguarda X509ContentType.Cert vs. X509ContentType.Pfx funziona come previsto:

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();
    }
}

E 'in uscita il seguente:

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

C'è un OpenSSL .NET involucro si possono trovare utili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top