简体   繁体   中英

How to tell if X.509 Certificate is Exportable?

I have a simple C# DotNet console app that enumerates the certificates in a location/store. It displays things like the following:

  • x509.SerialNumber
  • x509.Issuer
  • x509.Subject
  • x509.HasPrivateKey

Is there any property that will tell whether the Certificate is exportable? I could not find one, but I am fairly new to this.

If it's an RSA certificate you could do something like this:

RSACryptoServiceProvider rsa = cert.PrivateKey;
var isExportable = rsa.CspKeyContainerInfo.Exportable; 

There's not a reliable way of doing it, because you have to cross the boundary from "implementation independent" to "implementation dependent" -- exportability isn't inherent to certificates or keys, but a function of how the key was stored.

If you're only on Windows, and you're on Windows XP or older, this will work fairly reliably:

try
{
    ICspAsymmetricAlgorithm key = cert.PrivateKey;

    if (key != null)
    {
        return key.CspKeyContainerInfo.Exportable;
    }
}
catch (CryptographicException) {}

return whateverYouWantUnknownToBe;

Once you're on Vista or newer then it's possible to get certificates where HasPrivateKey is true, but PrivateKey throws an "invalid provider specified" exception, to work around that you need to jump up to .NET 4.6.

// AllowExport says whether it can be exported in a PFX (encrypted key)
// AllowPlainTextExport says whether it can be exported as (e.g.) an RSAParameters structure
const CngExportPolicies RequiredPolicies = CngExportPolicies.AllowExport;

RSACng rsaCng = cert.GetRSAPrivateKey() as RSACng;

if (rsaCng != null)
{
    return (rsaCng.Key.ExportPolicy & RequiredPolicies) == RequiredPolicies;
}

// Requires 4.6.1
ECDsaCng ecdsaCng = cert.GetECDsaPrivateKey() as ECDsaCng;

if (ecdsaCng != null)
{
    return (ecdsaCng.Key.ExportPolicy & RequiredPolicies) == RequiredPolicies;
}

// Requires 4.6.2
DSACng dsaCng = cert.GetDSAPrivateKey() as DSACng;

if (dsaCng != null)
{
    return (dsaCng.Key.ExportPolicy & RequiredPolicies) == RequiredPolicies;
}

// previous code goes here.

But, ultimately, the only foolproof way is to actually try it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM