Question

Je pensais que ce serait simple, mais apparemment ce n'est pas. J'ai un certificat installé qui a une clé privée, exportables, et je veux exporter par programme avec la clé publique SEULEMENT. En d'autres termes, je veux un résultat équivalent à sélectionner « Ne pas exporter la clé privée » lors de l'exportation par certmgr et l'exportation vers .CER.

Il semble que toutes les méthodes de X509Certificate2.Export exportera la clé privée si elle existe, comme PKCS # 12, qui est à l'opposé de ce que je veux.

Est-il possible en utilisant C # pour cela, ou dois-je commencer à creuser dans CAPICOM?

Était-ce utile?

La solution

Pour toute autre personne qui pourrait avoir trébuché sur ce point, je compris. Si vous spécifiez X509ContentType.Cert comme le premier (et seul) paramètre à X509Certificate.Export, il exporte que la clé publique. D'autre part, en spécifiant X509ContentType.Pfx comprend la clé privée si l'on existe.

J'aurais juré que je voyais un comportement différent la semaine dernière, mais je dois avoir déjà eu la clé privée installée quand je testais. Quand je supprimé ce certificat aujourd'hui et a commencé à nouveau à partir de zéro, j'ai vu qu'il n'y avait pas de clé privée dans le cert exporté.

Autres conseils

J'ai trouvé le programme utile pour moi rassurant que la propriété RawData du certificat ne contient que la clé publique (MSDN ne sait pas à ce sujet), et que la réponse ci-dessus en ce qui concerne X509ContentType.Cert par rapport X509ContentType.Pfx fonctionne comme prévu:

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

Il produit les éléments suivants:

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

Il y a un OpenSSL wrapper .NET vous pouvez trouver utile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top