使用golang和tls,如何将rawCerts[][]字节(传递给VerifyPeerCertificate)转换为x509.证书?

使用golang和tls,如何将rawCerts[][]字节(传递给VerifyPeerCertificate)转换为x509.证书?,go,ssl,ssl-certificate,Go,Ssl,Ssl Certificate,上下文:我想建立到服务器的TLS连接,该服务器具有一个具有不同(但已知!)域的证书 因此,我想使用tls.Dial('tcp','real domain',conf),但要验证证书的域,就像它是另一个域一样(让我们称它为错误域),我知道服务器应该返回它 因此,我认为实现这一点的方法是覆盖客户机tls.Config中的VerifyPeerCertificate VerifyPeerCertificate获取rawCerts[][]字节作为参数,但要使用x509。验证我需要证书作为x509。证书类型

上下文:我想建立到服务器的TLS连接,该服务器具有一个具有不同(但已知!)域的证书

因此,我想使用
tls.Dial('tcp','real domain',conf)
,但要验证证书的域,就像它是另一个域一样(让我们称它为
错误域
),我知道服务器应该返回它

因此,我认为实现这一点的方法是覆盖客户机
tls.Config
中的
VerifyPeerCertificate

VerifyPeerCertificate
获取
rawCerts[][]字节
作为参数,但要使用
x509。验证
我需要证书作为
x509。证书
类型

问题是:如何转换作为参数传递给
VerifyPeerCertificate
rawCerts[][]字节
,将其转换为
x509.证书

我想这样使用它:

    conf := &tls.Config{
        VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
            verifyOptions := x509.VerifyOptions{
                DNSName:                   "wrong-domain",
                Roots:                     serverCertPool,
            }
            cert := &x509.Certificate{???} // How do I get the x509.Certificate out of the rawCerts [][]byte parameter?
            _, err := cert.Verify(verifyOptions)
            return err
        },
        InsecureSkipVerify: true, // We verify in VerifyPeerCertificate
    }

使用
cert,err:=x509.ParseCertificate(rawCerts[0])

ParseCertificate从给定的ASN.1 DER数据中解析单个证书

顺便说一句,调用
VerifyPeerCertificate
的函数也是这样做的:

// crypto/tls/handshake/handshake_client.go

func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
    for i, asn1Data := range certificates {
        cert, err := x509.ParseCertificate(asn1Data)
        if err != nil {
            c.sendAlert(alertBadCertificate)
            return errors.New("tls: failed to parse certificate from server: " + err.Error())
        }
        certs[i] = cert
    }

    // later on...
    
    if c.config.VerifyPeerCertificate != nil {
        if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
            c.sendAlert(alertBadCertificate)
            return err
        }
    }