C# 根据自签名证书颁发机构验证服务器证书

C# 根据自签名证书颁发机构验证服务器证书,c#,.net,ssl,x509certificate,C#,.net,Ssl,X509certificate,我有使用SSL加密TCP连接(自定义协议)相互通信的自定义服务器/客户端应用程序。为了设置服务器证书,我创建了一个自签名证书颁发机构,并使用它来为服务器使用的证书签名。在客户端,我想验证我连接的服务器的证书是否由我的自签名CA签名 我通过C++提供了SSL::上下文:使用LoopyValuyYFILE()函数来实现自签名CA证书。我希望在C#客户机中实现相同的功能,但是.NET SSL的内容对于信任不在Windows信任存储中的证书似乎要严格得多 到目前为止,我在四处寻找的过程中找到了几个部分解

我有使用SSL加密TCP连接(自定义协议)相互通信的自定义服务器/客户端应用程序。为了设置服务器证书,我创建了一个自签名证书颁发机构,并使用它来为服务器使用的证书签名。在客户端,我想验证我连接的服务器的证书是否由我的自签名CA签名

我通过C++提供了SSL::上下文:使用LoopyValuyYFILE()函数来实现自签名CA证书。我希望在C#客户机中实现相同的功能,但是.NET SSL的内容对于信任不在Windows信任存储中的证书似乎要严格得多

到目前为止,我在四处寻找的过程中找到了几个部分解决方案。显然地我尝试了代码,但手动创建的链仍然抱怨根证书不可信,就像传递到验证函数的原始链一样。有一个选项,但这似乎意味着它将接受任何自签名证书,这绝对不是我想要的

这似乎是最接近我想要的代码,但如上所述,我的问题是,它仍然抱怨我添加到外部存储的证书是自签名的。有没有办法说服X509Chain信任我提供的证书

bool remoteCertificateValidationCallback(
    object sender, X509Certificate certificate, X509Chain chain,
    SslPolicyErrors sslPolicyErrors)
{
    // make sure certificate was signed by our CA cert
    X509Chain verify = new X509Chain();
    verify.ChainPolicy.ExtraStore.Add(secureClient.CertificateAuthority); // add CA cert for verification
    //verify.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; // this accepts too many certificates
    verify.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // no revocation checking
    verify.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
    if (verify.Build(new X509Certificate2(certificate)))
    {
        return true; // success?
    }
    return false;
}

我怀疑您的私有CA证书未安装在当前系统(运行代码的系统)上,或者安装不正确。根CA证书必须安装在计算机stire的受信任根CA容器中,而不是当前用户存储中。默认情况下,
X509Chain
使用计算机存储查找受信任的锚

此外,您的代码不会执行您想要的操作。它将接受并传递任何公共受信任的根CA。相反,您需要比较
X509Chain.chainements
中的最后一个元素,以及所包含的证书是否是您期望的证书(通过比较指纹值)。愚蠢的修正应该适用于:

if (verify.Build(new X509Certificate2(certificate)))
{
    return verify.ChainElements[verify.ChainElements.Count - 1]
        .Certificate.Thumbprint == cacert.thumbprint; // success?
}
return false;

其中,
cacert
是您的根CA证书。

您是正确的,我没有将CA证书安装到受信任的存储中。我希望避免那样做。但似乎更可能的是,我无法使用.NET所拥有的内置工具完成我想要的任务。我刚刚注意到,在相关文档中,它们看起来几乎相同(它们没有指定所使用的CA是否是自签名的)。它没有很好的答案。
X509Chain.Build
内部调用
CertCreateCertificateChaineEngine
函数,该函数依赖本地证书存储建立信任。您可以通过删除外部IF语句而不使用方法result来避免此要求。这就足够回答您的确切问题了。因此,比较两个证书的指纹属性将检查它们是否相同?这可能会起作用,我甚至可以使用传入的
chain
变量(该变量具有来自服务器的正确链)。我是否可以检查
链.ChainStatus
仅包含
不可信项
,以确保该链也是有效的,而不只是在末尾添加CA?是的,指纹比较是比较证书最可靠的方法之一(最准确的是二进制比较)。请注意,在.NET 5中,现在可以通过将链策略设置为
X509ChainTrustMode.CustomRootTrust
来执行证书固定。