【问题标题】:Golang certificate validationGolang 证书验证
【发布时间】:2017-12-09 23:01:13
【问题描述】:

我正在使用 Go 通过自定义根 CA 执行 HTTPS 请求。根 CA 是我身边唯一的证书。

我的代码如下所示:

// performRequest sets up the HTTPS Client we'll use for communication and handle the actual requesting to the external
// end point. It is used by the auth and collect adapters who set their response data up first.
func performRequest(rawData []byte, soapHeader string) (*http.Response, error) {
  conf := config.GetConfig()

  // Set up the certificate handler and the HTTP client.
  certPool := x509.NewCertPool()
  certPool.AppendCertsFromPEM(certificate)
  client := &http.Client{
    Transport: &http.Transport{
      TLSClientConfig: &tls.Config{
        RootCAs:            certPool,
        InsecureSkipVerify: false,
      },
    },
  }

  req, err := http.NewRequest(http.MethodPost, baseURL, bytes.NewBuffer(rawData))
  if err != nil {
    return nil, err
  }

  // Sets the SOAPAction and Content-Type headers to the request.
  req.Header.Set("SOAPAction", soapHeader)
  req.Header.Set("Content-Type", "text/xml; charset=UTF-8")

  // Send request as our custom client, return response
  return client.Do(req)
}

我得到的错误是这样的:

2017/12/09 21:06:13 Post https://secure.site: x509: certificate is not valid for any names, but wanted to match secure.site

我一直无法准确找出造成这种情况的原因。检查 CA 证书的 SAN 时,我没有 secure.site 那里(根本没有名字,如错误所述),但我看不出我是怎么做错的。

我应该怎么做才能解决这个问题?

【问题讨论】:

    标签: ssl go cryptography x509


    【解决方案1】:

    你需要做两件事:

    1. 服务器端也要添加CA证书,CA需要各方都知道。
    2. 在服务器上生成并使用服务器证书(证书中包含主机名)。服务器证书需要由 CA 签名。

    您可以在 here(第一个 google 示例)上找到这方面的示例

    编辑:澄清一下,错误是由于您试图安全地连接到远程主机。默认情况下,go 客户端会查找服务器返回的有效证书。

    有效的手段(除其他外):

    1. 它由已知的 CA 签名
    2. 它在CommonNameSubject Alternative Name: DNS/IP 字段中包含服务器的ip/dns(您传递给http.NewRequest 的那个)。

    最终编辑

    服务器证书包含正确的Common Name 设置为服务器主机名,但它还包含一个Subject Alternative Name 设置为电子邮件地址。

    https://groups.google.com/a/chromium.org/forum/#!topic/security-dev/IGT2fLJrAeo 中所述,如果找到 SAN,Go 现在会忽略 Common Name

    【讨论】:

    • 证书已经在我移植的另一个系统中生产。此外,运行wget https://secure.site --ca-certificate=/the/certificate 也可以。我的实现一定有问题。
    • 您能否使用$ openssl s_client -showcerts -connect secure.site:443 转储服务器证书的内容,我们正在寻找Server certificate: subject 部分。
    • Server certificate subject=/C=SE/O=Company Inc./OU=Server1024/serialNumber=165563372191/CN=secure.site issuer=/C=SE/O=Issues Inc./CN=Issuer Inc. EID CA v2
    • 这很奇怪。我很确定证书有效性检查在主机检查之前进行,因此您的 CA 应该没问题。只是为了确保,您可以将 --verify_hostname secure.site 添加到 openssl 命令吗?它应该以Verify return code: 0 (ok) 结尾
    • "...如果找到 SAN,Go 现在会忽略通用名称..." 根据 RFC 2818,这是一个纯粹而简单的错误。
    猜你喜欢
    • 1970-01-01
    • 2016-08-31
    • 2017-06-13
    • 2019-03-29
    • 2014-06-24
    • 1970-01-01
    • 2022-06-17
    • 2021-04-13
    • 1970-01-01
    相关资源
    最近更新 更多