检查http.NewRequest中服务器SSL / TLS证书的指纹

时间:2014-11-19 00:19:33

标签: ssl go

如何在golang中的http请求中检查服务器SSL / TLS证书的指纹?

这个ruby code显示我想要在Go中做什么:

  @verify_callback = proc do |preverify_ok, store_context|
    if preverify_ok and store_context.error == 0
      certificate = OpenSSL::X509::Certificate.new(store_context.chain[0])
      fingerprint = Digest::SHA1.hexdigest(certificate.to_der).upcase.scan(/../).join(":")
      $valid_fingerprints.include?(fingerprint)
    else
      false
    end
  end

2 个答案:

答案 0 :(得分:4)

通常,在Go中生成证书指纹的过程非常简单。如果您已经存储了x509.Certificate结构,存储在cert中,那么您需要做的只是

sha1Fingerprint := sha1.Sum(cert.Raw)

在请求完成后从HTTP响应结构中获取证书也非常简单(使用resp.TLS.PeerCertificates),但看起来并不是您需要的。

如果您需要在TLS连接设置时访问服务器的证书,我认为您需要创建自己的http.Transport并将其交给DialTLS的自定义实施。然后,在配置http.Client以发出出站请求时,您将使用该传输。

在您的自定义DialTLS功能中,您可以访问服务器证书链等连接状态信息,并且可以从那里执行SHA1指纹生成。

答案 1 :(得分:0)

您可能不应该自己实施证书检查,但让net / http根据您提供的有效CA进行检查。此外,通常直接使用指纹是不值得的。

例如,这是您设置要求客户端使用证书进行身份验证的HTTPS服务器的方法。客户端证书必须由CA签名,否则SSL / TLS握手将停止。

    // Server's own certificate & key
    cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
    if err != nil {
       panic(err)
    }

    // Load the CA certificate(s)
    capool := x509.NewCertPool()
    cacert, err := ioutil.ReadFile("ca.crt")
    if err != nil {
       panic(err)
    }
    capool.AppendCertsFromPEM(cacert)

    // Server configuration
    config := tls.Config{Certificates: []tls.Certificate{cert}, ClientCAs: capool, ClientAuth: tls.RequireAndVerifyClientCert}
    config.NextProtos = []string{"http/1.1"}
    config.Rand = rand.Reader // Strictly not necessary, should be default

    // TLS web server
    myTLSWebServer := &http.Server{Addr: "myaddress", TLSConfig: &config, Handler: nil}

    // .. proceed with setting handlers etc
    http.HandleFunc("/", myHandler)

    // Bind to port and start the server up
    conn, err := net.Listen("tcp", settings.ServiceAddress)
    if err != nil {
       panic(err)
    }
    tlsListener := tls.NewListener(conn, &config)
    myTLSWebServer.Serve(tlsListener)

阅读tls.Config的文档将通过更改参数( ClientAuth,ClientCAs,Certificates,RootCAs )向您显示,您可以轻松选择不同的模式来检查证书。您通常会在错误中返回失败。

如果您真的坚持要检查指纹,可以从请求TLS *tls.ConnectionState检索TLS状态。我认为你应该使用该结构中的 Signature 进行指纹识别。在我的脑海中,大致沿着

的方向发展。
func lol(r *http.Request) {
    tls := r.TLS
    if tls != nil {
       // Try the first one for simplicity
       cert := tls.PeerCertificates[0]
       signature := cert.Signature
       // Do something with the signature
    }
}

应该这样做。