github.com/avenga/couper@v1.12.2/internal/tls/certificate.go (about)

     1  package tls
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/ecdsa"
     6  	"crypto/ed25519"
     7  	"crypto/rsa"
     8  	"crypto/tls"
     9  	"crypto/x509"
    10  	"encoding/pem"
    11  	"strings"
    12  
    13  	"github.com/avenga/couper/errors"
    14  )
    15  
    16  // ParseCertificate reads a certificate from the given bytes.
    17  // Either as PEM format where chained ones are considered or just plain DER format.
    18  func ParseCertificate(cert, key []byte) (certificate tls.Certificate, err error) {
    19  	certBytes := cert[:]
    20  	// try PEM format
    21  	var keyDERBlock *pem.Block
    22  	for {
    23  		var certDERBlock *pem.Block
    24  		certDERBlock, certBytes = pem.Decode(certBytes)
    25  		if certDERBlock == nil {
    26  			if len(certificate.Certificate) > 0 {
    27  				certificate.Leaf, err = x509.ParseCertificate(certificate.Certificate[0])
    28  				if err != nil {
    29  					return certificate, err
    30  				}
    31  
    32  				// Option to combine both into one file.
    33  				if keyDERBlock != nil {
    34  					certificate.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes)
    35  					if err != nil {
    36  						return certificate, err
    37  					}
    38  				}
    39  			}
    40  			break
    41  		}
    42  		if certDERBlock.Type == "CERTIFICATE" {
    43  			certificate.Certificate = append(certificate.Certificate, certDERBlock.Bytes)
    44  		} else if strings.HasSuffix(certDERBlock.Type, " PRIVATE KEY") {
    45  			keyDERBlock = certDERBlock
    46  		}
    47  	}
    48  
    49  	// assume DER format
    50  	if len(certificate.Certificate) == 0 {
    51  		var x509Certificate *x509.Certificate
    52  		x509Certificate, err = x509.ParseCertificate(cert)
    53  		if err != nil {
    54  			return certificate, err
    55  		}
    56  
    57  		certificate = tls.Certificate{
    58  			Certificate: [][]byte{cert},
    59  			Leaf:        x509Certificate,
    60  		}
    61  	}
    62  
    63  	if certificate.PrivateKey == nil && len(key) > 0 {
    64  		keyBytes := key[:]
    65  		keyDERBlock, _ = pem.Decode(key)
    66  		if keyDERBlock != nil {
    67  			keyBytes = keyDERBlock.Bytes
    68  		}
    69  		certificate.PrivateKey, err = parsePrivateKey(keyBytes)
    70  	}
    71  
    72  	return certificate, err
    73  }
    74  
    75  // Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates
    76  // PKCS #1 private keys by default, while OpenSSL 1.0.0 generates PKCS #8 keys.
    77  // OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three.
    78  func parsePrivateKey(der []byte) (crypto.PrivateKey, error) {
    79  	if key, err := x509.ParsePKCS1PrivateKey(der); err == nil {
    80  		return key, nil
    81  	}
    82  	if key, err := x509.ParsePKCS8PrivateKey(der); err == nil {
    83  		switch key := key.(type) {
    84  		case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey:
    85  			return key, nil
    86  		default:
    87  			return nil, errors.Configuration.Message("tls: found unknown private key type in PKCS#8 wrapping")
    88  		}
    89  	}
    90  	if key, err := x509.ParseECPrivateKey(der); err == nil {
    91  		return key, nil
    92  	}
    93  
    94  	return nil, errors.Configuration.Message("tls: failed to parse private key")
    95  }