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

时间:2014-12-05 01:26:44

标签: c# .net ssl x509certificate

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

通过使用load_verify_file()函数为ssl :: context提供自签名CA证书,我能够在C ++中使用boost。我想在C#客户端中实现相同的功能,但是对于信任不在Windows信任库中的证书,.NET SSL的内容似乎要严格得多。

到目前为止,我找到了几个部分解决方案。显然X509Chain is the class to use to verify SSL certificates。我尝试过代码like this,但手动创建的链仍然抱怨根证书是不可信的,就像传递给验证函数的原始链一样。 ignore unknown certificate authorities有一个选项,但这似乎意味着它将接受任何自签名证书,这绝对不是我想要的。

这是似乎最接近我想要的代码,但如上所述,我有一个问题,它仍然抱怨我添加到ExtraStore的证书是自签名的。有没有办法说服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;
}

1 个答案:

答案 0 :(得分:6)

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

此外,您的代码无法执行您想要的操作。它将接受并传递任何公开信任的根CA.相反,您需要比较X509Chain.ChainElements中的最后一个元素,包含的证书是否是您期望的证书(通过比较指纹值)。应该采用以下措施:

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

其中cacert是您的根CA证书。