C# 如何在单平台和多平台上使用X509Certificate2正确验证SSL证书

C# 如何在单平台和多平台上使用X509Certificate2正确验证SSL证书,c#,mono,ssl-certificate,x509certificate2,C#,Mono,Ssl Certificate,X509certificate2,我必须在一个非浏览器应用程序中验证几个SSL证书,用于应在IOS、Android和Linux上运行的HttpRequests和websocket连接。 当通过HTTPS进行连接时,我会收到一个X509Certificate2对象数组,其中最下面的是服务器证书,最上面的是根CA(希望如此)。例如,当我连接到https://google.com我收到3份X509Certificate2,其中包含以下主题名称。名称: 0:“CN=google.com,O=google Inc,L=Mountain

我必须在一个非浏览器应用程序中验证几个SSL证书,用于应在IOS、Android和Linux上运行的
HttpRequests
websocket
连接。 当通过
HTTPS
进行连接时,我会收到一个
X509Certificate2
对象数组,其中最下面的是服务器证书,最上面的是根CA(希望如此)。例如,当我连接到
https://google.com
我收到3份
X509Certificate2
,其中包含以下
主题名称。名称

  • 0:
    “CN=google.com,O=google Inc,L=Mountain View,S=California,C=US”
  • 1:
    “CN=Google互联网管理局G2,O=Google Inc,C=US”
  • 2:
    “CN=GeoTrust Global CA,O=GeoTrust Inc.,C=US”
我现在需要使用给定的信息和以下验证来验证证书验证:

  • 信任链验证
  • 主机名验证
  • 证书撤销验证
我尝试了什么,但没有理解,失败了:

当我对每个证书分别调用
X509Certificate2.Verify()
方法时,每次它都返回
false
。我也不明白为什么它可以返回任何其他内容,然后
false
,因为验证是独立进行的。相反,根据我对理论的理解,应该检查完整的链,即所有证书

然后我使用了
X509Chain
类:

foreach (X509Certificate2 cert in allthreecerts)
    {
        X509Chain chain = new X509Chain();
        X509ChainPolicy chainPolicy = new X509ChainPolicy()
        {
            RevocationMode = X509RevocationMode.Offline,
            RevocationFlag = X509RevocationFlag.EntireChain
        };
        chain.ChainPolicy = chainPolicy;
        if (!chain.Build(cert))
        {
            foreach (X509ChainElement chainElement in chain.ChainElements)
            {
                foreach (X509ChainStatus chainStatus in chainElement.ChainElementStatus)
                {
                    Debug.WriteLine(chainStatus.StatusInformation);
                }
            }
        }
    }            
这将为每个证书打印出
RevocationStatusUnknown
OfflineRevocation

同样,我不明白为什么这应该起作用,因为构建了一个链,每个证书都是独立的。父证书不应该是子证书的颁发,而应该是根CA吗

我认为我需要的东西,但不知道如何使用。

为了验证证书吊销,所有客户端都需要提供证书吊销列表。我在哪里可以得到这样一个列表,我在哪里加载它,并告诉链使用这个本地列表

信任验证链也存在同样的问题,因为最后一个证书应该是根证书,并且必须是受信任的根CA的客户端之一。例如,我必须加载Firefox附带的所有根CA,并检查根CA是否是其中之一?最好的方法是什么

[更新] 在
google.com
示例中,我粘贴了两个完全相同的证书主题名称,这是一个复制粘贴错误

当通过HTTPS进行连接时,我会收到一个X509Certificate2对象数组,其中最下面的是服务器证书,最上面的是根CA(希望如此)

如果确实从SSL服务器获取了根ca证书,则SSL服务器配置不正确。它应该返回其服务器证书和除根CA证书之外的整个链

当我对每个证书单独调用X509Certificate2.Verify()方法时,每次都返回false


如X509Certificate2中所述。验证方法
此方法为证书构建一个简单的链,并将基本策略应用于该链。
现在什么是
基本策略
我不知道。但是,
ChainPolicy
的默认值之一是
RevocationMode=X509RevocationMode.Online
。至于Mono,可以找到这种方法的来源。可以找到X509Chain的Mono实现源代码

这将为每个证书打印RevocationStatusUnknown和OfflineRevocation

当您指定RevocationMode=X509RevocationMode.Offline并且缓存中没有CRLs或OCSP响应(可能)时,它还应该打印什么

为了验证证书吊销,所有客户端都需要提供证书吊销列表。我在哪里可以得到这样一个列表,我在哪里加载它,并告诉链使用这个本地列表

链中的每个证书(根ca证书除外)都包含指向CRL的链接。NET和最有可能的Mono也是一个实现,它将在证书中找到指向CRL的链接,将下载它并检查证书是否被吊销

信任验证链也存在同样的问题,因为最后一个证书应该是根证书,并且必须是受信任的根CA的客户端之一。例如,我必须加载Firefox附带的所有根CA,并检查根CA是否是其中之一?最好的方法是什么

否,
RevocationFlag=X509RevocationFlag.EntireChain
将使用mono使用的某些商店为您执行此操作。我不知道它是否是Firefox商店,但在Linux上它有自己的商店,您可以从Firefox商店导入根ca证书。检查ChainElements并亲自查看它找到了什么证书


我建议您仅使用SSL服务器证书构建链(因为这将向上检查链中的所有证书),并使用
RevocationMode=X509RevocationMode.Online
RevocationFlag=X509RevocationFlag.EntireChain
。我还将尝试将X509Chain的属性设置为从SSL服务器获得的证书列表。在构建方法之后,我将使用X509Chain对象的chceck ChainStatus属性,该对象是一个状态数组。我会选择所有未设置为无错误的状态。如果有任何这样的状态,我会抛出并记录每个X509ChainStatus.status和


HTH

RevocationMode=X509RevocationMode.离线
——切换到在线。客户端必须具有本地CRL/OCSP缓存才能在脱机模式下成功验证吊销。这就是重点。我正在实现“客户机”。那么我如何提供这样的CRL。这就是我要问的问题。CRL是重试