我必须在非浏览器应用程序中验证应该在IOS,Android和Linux上运行的HttpRequests
和websocket
连接的多个SSL证书。
当通过HTTPS
发生连接时,我会收到一组X509Certificate2
个对象,其中底部的是服务器证书,而最高的是根CA(希望如此)。例如,当我连接到https://google.com
时,我收到3 X509Certificate2
以及SubjectName.Name
:
"CN=google.com, O=Google Inc, L=Mountain View, S=California, C=US"
"CN=Google Internet Authority G2, O=Google Inc, C=US"
"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
示例中制作了一个复制粘贴错误,其中我粘贴了两个相同的证书使用者名称。
答案 0 :(得分:2)
当通过HTTPS发生连接时,我收到一个X509Certificate2对象数组,其中底部的是服务器证书,最高的是根CA(希望如此)。
如果您确实从SSL服务器获得了root ca证书,则说明SSL服务器配置不正确。它应该返回其服务器证书和整个链除了根CA证书。
当我独立调用每个证书上的X509Certificate2.Verify()方法时,它每次都返回false。
正如X509Certificate2.Verify方法的documentation中所述[{1}}现在我不知道This method builds a simple chain for the certificate and applies the base policy to that chain.
是什么。但是,the base policy
的默认值为ChainPolicy
。至于Mono,可以找到此方法的来源here。可以找到X509Chain的Mono实现源here。
这将为每个证书打印出RevocationStatusUnknown和OfflineRevocation。
当您指定RevocationMode = X509RevocationMode.Offline且缓存中可能没有CRL或OCSP响应时,它还应该打印什么?
为了验证证书吊销,所有客户端都需要提供证书吊销列表。我在哪里获得这样的列表以及在哪里加载它并告诉链使用这个本地列表?
链中的每个证书(除根证书以外)都包含一个到CRL的链接(或多个链接)。 .NET和很可能Mono has的实现将在证书中找到CRL的链接,将下载它并检查证书是否未被撤销。
同样的问题是信任链验证,因为上次认证应该是根证书,并且必须是客户端受信任的根CA之一。所以我必须加载,例如,Firefox附带的所有根CA,并检查根CA是否是其中之一?最好的方法是什么?
不,RevocationMode = X509RevocationMode.Online
会使用单声道使用的商店为您执行此操作。我不知道它是否是Firefox商店,但在Linux上它有自己的商店,你可以从Firefox商店导入root ca证书。检查ChainElements并亲自查看它找到的证书。
我建议您使用RevocationFlag = X509RevocationFlag.EntireChain
和RevocationMode = X509RevocationMode.Online
仅使用SSL服务器证书构建链(因为这会检查链中的所有证书)。我还尝试将X509Chain的ExtraStore属性设置为您从SSL服务器获得的证书列表。在Build方法之后,我将chceck X509Chain对象的ChainStatus属性,这是一个状态数组。我会选择所有未将X509ChainStatus.Status设置为NoError的状态。如果有任何此类状态,我会抛出并记录每个X509ChainStatus.Status和X509ChainStatus.StatusInformation。
HTH