使用 golang 双向 TLS 身份验证信任特定客户端

zed*_*dix 5 ssl go

我已经在 Go 中成功设置了 TLS 相互身份验证客户端/服务器一段时间了,但现在希望进行一些小的调整。

具体来说,我想知道是否有一种方法只需要特定的客户端证书即可进行相互身份验证。

我目前正在使用这样的东西:

    // Load cert and build pool
    caCert, _ := ioutil.ReadFile(caPath)        
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)

    // Require client authentication
    tlsConfig := &tls.Config{
        ClientAuth: tls.RequireAndVerifyClientCert,
        ClientCAs: caCertPool,
    }
Run Code Online (Sandbox Code Playgroud)

效果很好,但是如果我正在读取的 PEM 文件实际上是一个证书链(A 由 B 颁发,B 是根 CA),这实际上最终会信任 B 颁发的任何证书,但我不这样做想。

有什么方法可以调整此代码以仅信任特定的 A 证书吗?

看来,如果我只在加载的 PEM 文件中包含 A,服务器握手代码会告诉客户端“将由 A 签名的所有证书发送给我”,这当然不是我想要的,因为证书 A 不是由 A 签名的。

理想情况下,我想说“您特别需要证书 A”才能成功连接。有这样的机制吗?

Mar*_*arc 6

没有任何机制可以为您执行此操作,但从go 1.8开始,您可以使用tls.ConfigVerifyPeerCertificate对象中的字段指定自己的回调(这在服务器端和客户端都有效)。

这需要一个具有以下签名的方法:

func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
Run Code Online (Sandbox Code Playgroud)

根据文档:

它接收对等方提供的原始 ASN.1 证书以及正常处理发现的任何经过验证的链。

证书验证已经运行,因此您只需应用特定逻辑:检查叶证书(每个链中的第一个)并verifiedChains检查该证书是否在允许的证书列表中(仅A在您的情况下)。如果不是:返回错误并且握手将失败。