如何根据 Go 中的发行链验证证书?
How to verify a certificate against an issuing chain in Go?
我想根据发行链验证 PEM 证书,该发行链也是一个 .pem
文件,其中包含多个由换行符分隔的证书,如本要点 https://gist.github.com/kurtpeek/8bf3282e344c781a20c5deadac75059f 所示。我用 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
我相信这个错误是在 https://golang.org/src/crypto/x509/verify.go 的第 790 行返回的:
if len(chains) == 0 {
return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
}
换句话说,Verify()
方法无法根据提供的选项构建任何 chains
。我已经尝试将中间体(要点中显示的 issuing_chain.pem
中的前两个)拆分成一个单独的 PEM 文件,并将它们作为 Intermediates
添加到 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 选项,因为 "an empty list means ExtKeyUsageServerAuth"。您还必须返回到单独提供中间证书的代码版本:
chain, err := cert.Verify(x509.VerifyOptions{
Roots: roots,
Intermediates: inters,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})
在操场上试试:https://play.golang.org/p/1BNLthzu5Tz。请注意,playground 需要 CurrentTime 选项才能正确验证。在其他地方复制时删除它!
我想根据发行链验证 PEM 证书,该发行链也是一个 .pem
文件,其中包含多个由换行符分隔的证书,如本要点 https://gist.github.com/kurtpeek/8bf3282e344c781a20c5deadac75059f 所示。我用 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
我相信这个错误是在 https://golang.org/src/crypto/x509/verify.go 的第 790 行返回的:
if len(chains) == 0 {
return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
}
换句话说,Verify()
方法无法根据提供的选项构建任何 chains
。我已经尝试将中间体(要点中显示的 issuing_chain.pem
中的前两个)拆分成一个单独的 PEM 文件,并将它们作为 Intermediates
添加到 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 选项,因为 "an empty list means ExtKeyUsageServerAuth"。您还必须返回到单独提供中间证书的代码版本:
chain, err := cert.Verify(x509.VerifyOptions{
Roots: roots,
Intermediates: inters,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})
在操场上试试:https://play.golang.org/p/1BNLthzu5Tz。请注意,playground 需要 CurrentTime 选项才能正确验证。在其他地方复制时删除它!