如何在 golang 中的 http 请求期间检查服务器 SSL/TLS 证书的指纹?
这个ruby 代码显示了我想在 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
Run Code Online (Sandbox Code Playgroud)
一般来说,在 Go 中生成证书指纹的过程非常简单。如果你已经有一个x509.Certificate结构体,存储在 中cert,你需要做的就是
sha1Fingerprint := sha1.Sum(cert.Raw)
Run Code Online (Sandbox Code Playgroud)
在请求完成后从 HTTP 响应结构获取证书也很容易(使用resp.TLS.PeerCertificates),但这似乎不是您所需要的。
如果您需要访问服务器在TLS连接建立时间证明,我认为你需要创建自己的http.Transport,并把它自定义实现的DialTLS。然后,您将在配置http.Client以发出出站请求时使用该传输。
在您的自定义DialTLSfunc 中,您可以访问连接状态信息,例如服务器的证书链,并且您可以从那里执行 SHA1 指纹生成。
您可能不应该自己实现证书检查,而应该让 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)
Run Code Online (Sandbox Code Playgroud)
阅读tls.Config的文档将告诉您,通过更改参数(ClientAuth、ClientCAs、Certificates、RootCAs),您可以轻松选择不同的证书检查模式。您通常会收到错误返回的失败信息。
如果您确实坚持检查指纹,可以从 Request TLS *tls.ConnectionState检索 TLS 状态。我认为你可能应该使用该结构中的签名进行指纹识别..在我的脑海中,大致类似于
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
}
}
Run Code Online (Sandbox Code Playgroud)
应该可以解决问题。
| 归档时间: |
|
| 查看次数: |
5015 次 |
| 最近记录: |