如何根据Go中的颁发链验证证书?

如何根据Go中的颁发链验证证书?,go,certificate,x509,pki,Go,Certificate,X509,Pki,我想根据一个发行链验证一个PEM证书,该发行链也是一个.PEM文件,其中有多个证书由换行符分隔,如本要点所示。我用Certpool.AppendCertsFromPEM尝试过这一点,如下所示: package main import ( "crypto/x509" "encoding/pem" "io/ioutil" "github.com/sirupsen/logrus" ) func main() { caCertPEM, err := iout

我想根据一个发行链验证一个PEM证书,该发行链也是一个
.PEM
文件,其中有多个证书由换行符分隔,如本要点所示。我用
Certpool.AppendCertsFromPEM
尝试过这一点,如下所示:

package main

import (
    "crypto/x509"
    "encoding/pem"
    "io/ioutil"

    "github.com/sirupsen/logrus"
)

func main() {
    caCertPEM, err := ioutil.ReadFile("issuing_chain.pem")
    if err != nil {
        logrus.WithError(err).Fatal("read CA PEM file")
    }

    certPEM, err := ioutil.ReadFile("3007e750-e769-440b-9075-41dc2b5b1787.pem")
    if err != nil {
        logrus.WithError(err).Fatal("read cert PEM file")
    }

    block, rest := pem.Decode(certPEM)
    if block == nil {
        logrus.WithField("rest", rest).Fatal("Decode CA PEM")
    }

    cert, err := x509.ParseCertificate(block.Bytes)
    if err != nil {
        logrus.WithError(err).Fatal("parse certificate")
    }

    roots := x509.NewCertPool()
    roots.AppendCertsFromPEM(caCertPEM)

    chain, err := cert.Verify(x509.VerifyOptions{Roots: roots})
    if err != nil {
        logrus.WithError(err).Fatal("failed to verify cert")
    }

    logrus.Infof("issuing chain: %+v", chain)
}
但是,如果运行此命令,会出现以下错误:

FATA[0000] failed to verify cert                         error="x509: certificate specifies an incompatible key usage"
exit status 1
我相信此错误在以下第790行返回:

换句话说,
Verify()
方法无法根据提供的选项构建任何
链。我已经尝试将中间产物(在要点中显示的
发布链.pem
中的前两个)拆分到一个单独的pem文件中,并将它们作为
中间产物添加到
x509.VerifyOptions
,但我仍然得到相同的错误


根据Go中的颁发链验证证书的正确方法是什么?

您的叶证书仅用于客户端身份验证

$ openssl x509 -noout -text -in leaf.pem  | grep -A1 'Key Usage'
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication
如果这是有意的,则必须指定KeyUsages选项,因为。您还必须返回到单独提供中间证书的代码版本:

chain, err := cert.Verify(x509.VerifyOptions{
    Roots:         roots,
    Intermediates: inters,
    KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})

在操场上试试:。请注意,游乐场需要CurrentTime选项来正确验证。在其他地方复制时删除此选项

可能其中一些证书是中间证书。验证选项需要分别使用根和中间产物。
chain, err := cert.Verify(x509.VerifyOptions{
    Roots:         roots,
    Intermediates: inters,
    KeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})