Reputation: 57611
I'd like to verify a PEM certificate against an issuing chain which is also a .pem
file with several certificates separated by newline characters as shown in this gist, https://gist.github.com/kurtpeek/8bf3282e344c781a20c5deadac75059f. I've tried this with Certpool.AppendCertsFromPEM
as follows:
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)
}
However, if I run this I get the following error:
FATA[0000] failed to verify cert error="x509: certificate specifies an incompatible key usage"
exit status 1
I believe this error is returned on line 790 of https://golang.org/src/crypto/x509/verify.go:
if len(chains) == 0 {
return nil, CertificateInvalidError{c, IncompatibleUsage, ""}
}
In other words, the Verify()
method is unable to build any chains
from the options provided. I've tried splitting out the intermediates (the top two in the issuing_chain.pem
shown in the gist) into a separate PEM file and adding those as Intermediates
to the x509.VerifyOptions
, but I still get the same error.
What is the correct way to verify a certificate against an issuing chain in Go?
Upvotes: 3
Views: 7953
Reputation: 31720
Your leaf certificate is for client authentication only.
$ 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
If this is intentional, you must specify the KeyUsages option because "an empty list means ExtKeyUsageServerAuth". You also have to go back to your version of the code that provides the intermediate certs separately:
chain, err := cert.Verify(x509.VerifyOptions{
Roots: roots,
Intermediates: inters,
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
})
Try it on the playground: https://play.golang.org/p/1BNLthzu5Tz. Note that the playground requires the CurrentTime option to verify correctly. Remove this when copying elsewhere!
Upvotes: 5