go - 如何根据 Go 中的发行链验证证书?

标签 go certificate x509 pki

我想针对同样是 .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 文件,并将它们添加为 Intermediatesx509.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 选项才能正确验证。在其他地方复制时删除它!

关于go - 如何根据 Go 中的发行链验证证书?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59383823/

相关文章:

windows - 需要帮助使用 CertFindCertificateInStore() 按主题名称(X500 格式,CERT_X500_NAME_STR)查找证书?

java - 与 AD 通信时出错 - 重新协商期间服务器证书更改受到限制

x509v3 权限信息访问

go - 确保 goroutine 清理,最佳实践

linux - 无法从 git clone go.googlesource.com 克隆 Git 存储库

iOS 开发证书和配置文件,可以在 Mac 上没有互联网吗?

C# X509 证书验证,具有在线 CRL 检查,无需将根证书导入受信任的根 CA 证书存储

bash - 在 Docker 容器中启动 Golang Web 服务器

Go编译器技巧

openssl - 使用 OpenSSL 并希望使用多个 CA_DIR 来加载验证位置