如何在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
答案 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
}
}
应该这样做。