【问题标题】:HttpWebRequest doesn't seem to be sending a client SSL certificateHttpWebRequest 似乎没有发送客户端 SSL 证书
【发布时间】:2012-11-10 23:10:11
【问题描述】:

我正在尝试使用HttpWebRequest 来查询运行 nginx 的远程服务器。我需要提供客户端证书才能完成连接。

我正在做以下事情:

Dim Request As HttpWebRequest = DirectCast(WebRequest.Create(Url), HttpWebRequest)
Dim Cert = SSL.GetClientCertificate()
Request.ClientCertificates.Clear()
Request.ClientCertificates.Add(Cert)
Dim Response As WebResponse = Request.GetResponse()

(SSL.GetClientCertificate 只是一个辅助方法,它在本地计算机上打开My 存储并检索适当的证书(作为X509Certificate2)。正在返回正确的证书。我也尝试过加载在具有相同结果的文件中的证书中。)

就目前的情况而言,当我到达 Dim Response As... 并且它实际上尝试打开连接时,我收到一个 400 Bad Request 返回,并带有以下正文:

400 Bad Request
No required SSL certificate was sent
-----------------------------------
nginx/1.0.10

我们正在使用我们自己的 CA,它在我的机器上的 LocalMachine\TrustedRootCertificationAuthorities 中有一个证书。客户端证书有效但验证失败,因为我们的 CA 未公开 OCSP 端点。如果我创建一个 X509Chain 并要求它验证链而不检查撤销,一切都会通过。

所以我的问题是……为什么证书没有随请求一起发送?我认为它不应该在发送之前尝试验证客户端证书(这是服务器的工作)。

我不会在 Wireshark 日志中淹没您,但客户端没有发送证书。简而言之,我得到...

  • [Out] 客户您好
  • [In] 服务器你好
  • [输入]证书
  • [In] 服务器问候完成
  • [Out] 证书、客户端密钥交换、更改密码规范、加密握手消息
  • [In] 更改密码规范,加密握手消息
  • [Out] 应用程序数据(可能是 GET 请求)
  • [In] 应用程序数据(大概是 400)
  • [In] 加密警报(终止通道)

认为 nginx 正在做一些聪明的事情,而不是在我发送证书失败时死掉,而是重新协商以允许它发送 400 响应正文(而不是未能在第一名)

无论如何,我不会发送真正问题的证书。有谁知道为什么?

如果有帮助,nginx 的日志坚持没有发送证书(而不是证书无效):

2012/11/22 14:16:26 [info] 27755#0: *799 客户端在读取客户端请求标头时未发送所需的 SSL 证书,客户端:10.0.0.200,服务器:10.0.0.100,请求:“GET /state HTTP/1.1”,主机:“10.0.0.100”

请不要使用下面的代码 - 它效率低,不可靠,仅用于测试

Re:获取证书:

Public Shared Function GetClientCertificate() As X509Certificate2
    Dim Store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
    Dim Ret As X509Certificate2 = Nothing

    Try
        Store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
        For Each Certificate In Store.Certificates
            If Certificate.SubjectName.Name = "The subjectname of our certificate" Then
                Ret = Certificate
                Exit For
            End If
        Next
    Finally
        Store.Close()
    End Try
    Return Ret
End Function

【问题讨论】:

  • 运行应用程序的用户是否有权访问客户端证书的私钥(或:SSL.GetClientCertificate 做什么)?服务器是否确认您的根 CA 并将其列为受信任的颁发者?
  • @CodeCaster 我们已经达到了我的知识极限,如果我误解了,我们深表歉意……有问题的证书没有私钥 (Cert.HasPrivateKey = False)。该代码目前正在以我的身份运行(通过 iisexpress),但最终会在 IIS 中,这就是为什么我将证书放在机器级存储中,而不是用户级存储中。听起来对吗?
  • @CodeCaster 查看我的编辑以了解如何获得证书。在此之前,我也尝试过X509Certificate2.CreateFromCertFile("[Path to .cer]")。请注意,获得证书可能会被大量整理,我不喜欢它检查它的方式,但我需要让它正常工作,然后才能让它整齐地工作:/
  • @CodeCaster 我已经解决了这个问题,你是对的。您可以发表您的评论作为答案,以便我接受吗?谢谢
  • 我已经做到了。乐于助人。

标签: .net security ssl nginx httpwebrequest


【解决方案1】:

您需要具有可访问私钥的证书才能将其用作客户端(或服务器,就此而言)证书。

只要您授予任何需要使用证书访问其私钥的用户,就可以将证书存储在机器证书存储中。您不能使用 .cer 对客户端进行身份验证,因为它只包含公钥。您可以通过为您的用户安装客户端证书并使用浏览器访问 URL 来测试所有内容。如果您得到一个选择证书的弹出窗口,则它已正确安装(针对该用户)。

【讨论】:

    猜你喜欢
    • 2018-09-05
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 2020-03-19
    • 2012-03-27
    • 2013-06-06
    相关资源
    最近更新 更多