Use a particular CA for a SSL connection

泪湿孤枕 提交于 2020-01-02 14:48:54

问题


I'm reading through Support Certificates In Your Applications With The .NET Framework 2.0 trying to determine how to set a CA for a SSL connection.

Around half-way down the article under Validating Certificates, MSDN presents some code:

static void ValidateCert(X509Certificate2 cert)
{
    X509Chain chain = new X509Chain();

    // check entire chain for revocation 
    chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;

    // check online and offline revocation lists
    chain.ChainPolicy.RevocationMode = X509RevocationMode.Online | 
                                           X509RevocationMode.Offline;

    // timeout for online revocation list 
    chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);

    // no exceptions, check all properties
    chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

    // modify time of verification
    chain.ChainPolicy.VerificationTime = new DateTime(1999, 1, 1);

    chain.Build(cert);
    if (chain.ChainStatus.Length != 0)
        Console.WriteLine(chain.ChainStatus[0].Status);
    }

Then later:

// override default certificate policy
ServicePointManager.ServerCertificateValidationCallback =
    new RemoteCertificateValidationCallback(VerifyServerCertificate);

I feel like I'm missing something really obvious. For example, I don't want a callback - I just want to say, "establish a SSL connection, and here's the one CA to trust". But I don't see that in the code above.

X509Chain does not appear to have an add method to add a CA or root of trust. Shouldn't the CA be set before the callback? But I don't see that in the code above.

In Java, it would be done with a TrustManager (or TrustManagerFactory) after loading the particular CA you want to use (for an example, see Use PEM Encoded CA Cert on filesystem directly for HTTPS request?).

Question: How does one set a CA to use for an SSL connection in .Net or C#?


回答1:


The following code will avoid the Windows certificate stores and validate the chain with a CA on the filesystem.

The name of the function does not matter. Below, VerifyServerCertificate is the same callback as RemoteCertificateValidationCallback in SslStream class. It can also be used for the ServerCertificateValidationCallback in ServicePointManager.

static bool VerifyServerCertificate(object sender, X509Certificate certificate,
    X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    try
    {
        String CA_FILE = "ca-cert.der";
        X509Certificate2 ca = new X509Certificate2(CA_FILE);

        X509Chain chain2 = new X509Chain();
        chain2.ChainPolicy.ExtraStore.Add(ca);

        // Check all properties
        chain2.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;

        // This setup does not have revocation information
        chain2.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;

        // Build the chain
        chain2.Build(new X509Certificate2(certificate));

        // Are there any failures from building the chain?
        if (chain2.ChainStatus.Length == 0)
            return false;

        // If there is a status, verify the status is NoError
        bool result = chain2.ChainStatus[0].Status == X509ChainStatusFlags.NoError;
        Debug.Assert(result == true);

        return result;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }

    return false;
}

I have not figured out how to use this chain (chain2 below) by default such that there's no need for the callback. That is, install it on the ssl socket and the connection will "just work". And I have not figured out how install it such that its passed into the callback. That is, I have to build the chain for each invocation of the callback. I think these are architectural defects in .Net, but I might be missing something obvious.



来源:https://stackoverflow.com/questions/22516450/use-a-particular-ca-for-a-ssl-connection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!