How to operate with X509 certificates in .NET code

2019-08-12 08:34发布

问题:

I have some code that needs to work with X509 Certificate information. I have downloaded a sample that does this:

const string CertWithoutPrivateKey = "MII....";
const string CertWithPrivateKey = "MII...";

public static SecurityToken GetSigningToken(bool includePrivateKey)
{
    X509Certificate2 cert = null;
    if (includePrivateKey)
    {
        cert = new X509Certificate2(
            Convert.FromBase64String(CertWithPrivateKey), 
            "pw", X509KeyStorageFlags.PersistKeySet);
    }
    else
    {
        cert = new X509Certificate2(
            Convert.FromBase64String(CertWithoutPrivateKey));
    }
    return cert;
}

The code needs to be able to get the cert with the private key. The Saml2AuthenticationModule (from the WIF Extension for the SAML 2.0 Protocol) relies on this private key to decrypt information sent from a SAML Identity Provider.

I don't know much about certificates or encryption, but it seems to me that hard-coding the certificate into a class is not secure.

So, how should my code go about retrieving the cert with private key? Afaik, this code is only run one time at app startup (so probably also after an app pool recycle).

I could:

  1. Store the cert as an appSetting in config file. As long as appSettings are config encrypted, is this secure?
  2. Store the cert in a database.
  3. Store the cert as a file in bin/App_Data. Afaik this means it could not be read over the web, but would be in plain view to anyone who can access the host server. Imo if someone can get into my server, letting them read this cert is probably the least of my worries.

Are there any other options? What is most appropriate in this case?

回答1:

I'm not sure how WIF does it (you could probably use Reflector to see the internals of how it interacts with the certificate store), but it sounds like you are using WIF in an application hosted in IIS. If that's the case, WIF should take care of all the certificate interactions for you. You'll just have to make sure you have the following things set up:

  1. The identity model configuration section set up with references to the thumbprint of the certificate you are using to either encrypt or verify the digital signature of the token.
  2. The certificate needs to be registered in IIS
  3. The application pool's hosting identity needs to have permission to "read" the certificate to extract the private key information (see the accepted answer here)


回答2:

A certificate with or without private key can be save to X509 store of a user or the computer. This already has build-in Windows security that should be sufficient. You can use mmc with Certificates snap-in to add certificates to the store and manage them.

A reference to the certificate, for example, its name or thumbnail, can saved to the config file and used to retrieve the certificate. The retrieval may look like the following:

public static X509Certificate2 GetCertificate(string name)
{
    try
    {
        X509Store store = new X509Store (StoreLocation.LocalMachine);
        X509Certificate2Collection collection = store.Certificates;
        foreach (X509Certificate2 x509 in collection)
        {
            if (x509.FriendlyName.Equals(name)) 
            {
                return x509;
            }
        }
    }
    finally
    {
        store.Close();
    }
    return null;
}

Using Find on the collection is another (and cleaner) way to search certificates.