package x509util import ( "crypto/x509" "encoding/pem" "fmt" ) // ParseChain parses a certificate chain in PEM format. At least one // certificate must be in the chain. The first certificate must be a leaf, // whereas all other certificates must CA certificates (intermdiates/roots). // // Note: it is not checked if the certificate chain's root is trusted or not. func ParseChain(b []byte) ([]x509.Certificate, error) { var chain []x509.Certificate for { block, rest := pem.Decode(b) if block == nil { break } crt, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, fmt.Errorf("parse certificate: %v", err) } chain = append(chain, *crt) b = rest } if len(chain) == 0 { return nil, fmt.Errorf("no certificates in the provided chain") } if chain[0].IsCA { return nil, fmt.Errorf("leaf certificate has the CA bit set") } for _, crt := range chain[1:] { if !crt.IsCA { return nil, fmt.Errorf("non-leaf certificate without the CA bit set") } } return chain, nil }