【问题标题】:HttpListenerRequest.GetClientCertificate() not returning the complete certificate chainHttpListenerRequest.GetClientCertificate() 未返回完整的证书链
【发布时间】:2022-01-03 23:18:43
【问题描述】:

我有一个使用 C# 中的HttpListener 实现的 Web 服务器,有一个 Go 客户端与该服务器通信。作为要求的一部分,我需要在服务器上验证从客户端发送的证书,并且我正在从客户端发送证书链。我找到了方法HttpListenerRequest.GetClientCertificate() 来获取服务器上的证书,但我只能接收叶证书,但不能接收阻止我执行链验证的整个链。有没有办法使用 HttpListener 作为服务器来接收整个链。

PS:我尝试将相同的证书链发送到 Go 服务器,Go 在 Tls Config 中有 ssl 回调处理程序(VerifyPeerCertificate),使用它我可以读取整个证书链。我只想用 C# 中现有的 HttpListener 服务器来实现这一点。

编辑:我的客户端证书是一个链(客户端证书 + 中间 CA + 根 CA)。我将根 CA 预存储在受信任的根证书颁发机构中。我需要在 Windows 信任存储中获取中间 CA,以便我可以为客户端证书构建链,并且由于我无法预先存储中间 CA,因此我的想法是从客户端发送链并在何时提取中间 CA客户端与服务器对话。 由于我能够使用具有相同客户端的 Go 服务器接收完整的链,因此我可以确认客户端始终发送链,但不知何故,我们在 C# 中为HttpListener 提供的方法似乎忽略了该链。

【问题讨论】:

    标签: c# httplistener httplistenerrequest


    【解决方案1】:

    通常客户端只是发送其客户端证书,然后由服务器负责检查客户端证书是否可信。如果任何人都可以发送带有完整链的客户端证书,那么服务器可以接受任何证书颁发机构(包括任何被泄露的证书)。因此,颁发客户端证书的证书颁发机构的证书必须在服务器上受信任,以确保该颁发机构受信任,并且服务器可以请求该颁发机构以确保客户端证书未被撤销。在 Windows 上,这是通过将证书颁发机构的证书添加到受信任的根证书颁发机构存储中来完成的。

    HttpListenerRequest.GetClientCertificate() source 只加载一个证书。

    在服务器端检查完整的链。服务器必须能够连接到已签署客户端证书的 AIA 才能下载中间 CA。

                var chain = new X509Chain();
                chain.ChainPolicy = new X509ChainPolicy()
                {
                    DisableCertificateDownloads = false,
                    RevocationFlag = X509RevocationFlag.EntireChain,
                    RevocationMode = X509RevocationMode.Online,
                    UrlRetrievalTimeout = TimeSpan.Zero,
                    VerificationFlags = X509VerificationFlags.AllFlags
                };
    

    您可以尝试实现自己的HttpListenerRequest 并将其用作管道中的中间件。

    【讨论】:

    • 证书链包含证书+中间CA+根CA。我将 rootCA 预存储在受信任的根证书颁发机构存储中,但我仍然需要中间 CA(证书的签名者)来验证服务器上的链,我无法预存储它,因为它在我的服务器启动之前不可用。所以想法是在客户端联系服务器时获取中间 CA 并将其存储在 Trusted Root Certification Authorities 存储中。
    • 中级证书颁发机构是中级 CA 的最佳存储。当服务器启动时,您仍然可以以编程方式将中间 CA 添加到存储中以使其可用。另一种选择可能是使用X509ChainX509ChainPolicyX509ChainBuild() 方法来验证证书并且可能有更多信息。您确定客户端证书提供了足够的信息(授权信息访问)并且服务器可以联系授权的任何端点吗?
    • 如何在服务器启动时没有证书的情况下添加中间 CA 证书?我在通过HttpListenerRequest.GetClientCertificate() 收到的证书上尝试了X509Chain.Build(),并通过下面的代码访问了链中的证书,但我只能看到叶证书和链构建失败,因为我没有中间CA信任库中的证书。 foreach (var chainElement in chain.ChainElements) { var certInChain = chainElement.Certificate; }我确定客户端证书有完整的链。
    • 因为服务器无法从客户端证书上定义的 AIA 端点“在线”检索中间服务器。但严重的是,中间 CA 在服务器启动之前不可用……这意味着中间 CA 是非常短暂的,或者是在服务器上动态托管的。
    • 首先感谢您指出从服务器下载证书链的方法。不幸的是,客户端链中的证书都没有 AIA 标签,所以我不能使用你建议的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2018-04-27
    • 2015-08-22
    • 2016-11-05
    • 1970-01-01
    • 2013-06-08
    • 2017-01-21
    相关资源
    最近更新 更多