C#从网站下载所有https证书

时间:2017-10-29 11:12:07

标签: c# ssl server certificate x509certificate

我想将所有证书从URL保存到磁盘。例如, https://www.google.de

如果我使用Firefox浏览此页面,我可以看到三个证书。 enter image description here

使用Firefox我可以将它们全部导出,并将它们保存到磁盘。

所以我想在C#中这样做。 我开始使用以下代码获取证书..

    /// <summary>
    /// Get and write certificate from URL into file in path
    /// </summary>
    /// <param name="_URL">URL of website with certficate</param>
    /// <param name="_path">Path where you want to store certificate</param>
    private static void SaveCertificate(String _URL, String _path)
    {
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_URL);
            request.AllowAutoRedirect = false;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            response.Close();

            X509Certificate2 cert = new X509Certificate2(request.ServicePoint.Certificate);

            File.WriteAllText(_path, ExportToPEM(cert));
        }
        catch (Exception)
        {
        }
    }

    /// <summary>
    /// Export a certificate to a PEM format string
    /// </summary>
    /// <param name="_cert">The certificate to export</param>
    /// <returns>A PEM encoded string</returns>
    public static string ExportToPEM(X509Certificate2 _cert)
    {
        StringBuilder builder = new StringBuilder();

        try
        {
            builder.AppendLine("-----BEGIN CERTIFICATE-----");
            builder.AppendLine(Convert.ToBase64String(_cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
            builder.AppendLine("-----END CERTIFICATE-----");

        }
        catch (Exception)
        {
        }

        return builder.ToString();
    }

这段代码的问题是,我只得到一个证书三个。 (我得到的证书是firefox截图中标记的证书)

我也从这里尝试了解决方案SO Question,但它对我没用。

我的问题是,如何从URL获取所有证书?

1 个答案:

答案 0 :(得分:2)

获得证书链的一种方法是在ServerCertificateValidationCallback上实施request

这是一个接受参数的函数:

(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)

这通常用于验证证书和链,但在这种情况下,我们只是使用它来访问证书链。它确实感觉很像黑客,但它应该工作。我已根据您发布的代码实施了概念验证。代码将证书输出到控制台窗口。

   public static void Main(string[] args)
    {
        SaveCertificate("https://www.google.de", "");
    }
    /// <summary>
    /// Get and write certificate from URL into file in path
    /// </summary>
    /// <param name="_URL">URL of website with certficate</param>
    /// <param name="_path">Path where you want to store certificate</param>
    private static void SaveCertificate(string url, string path)
    {

            var request = (HttpWebRequest)WebRequest.Create(url);
            request.AllowAutoRedirect = false;
            request.ServerCertificateValidationCallback = ServerCertificateValidationCallback;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            response.Close();
            Console.ReadLine();

    }

    private static bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        foreach (var cer in chain.ChainElements)
        {
            Console.WriteLine(cer.Certificate.FriendlyName);
            Console.WriteLine(ExportToPem(cer.Certificate));
        }

        return true;
    }

    /// <summary>
    /// Export a certificate to a PEM format string
    /// </summary>
    /// <param name="_cert">The certificate to export</param>
    /// <returns>A PEM encoded string</returns>
    public static string ExportToPem(X509Certificate2 cert)
    {
        StringBuilder builder = new StringBuilder();

        try
        {
            builder.AppendLine("-----BEGIN CERTIFICATE-----");
            builder.AppendLine(Convert.ToBase64String(cert.Export(X509ContentType.Cert), Base64FormattingOptions.InsertLineBreaks));
            builder.AppendLine("-----END CERTIFICATE-----");

        }
        catch (Exception)
        {
        }

        return builder.ToString();
    }