github.com/searKing/golang/go@v1.2.117/crypto/tls/cert.go (about)

     1  // Copyright 2022 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  import (
     8  	"crypto/tls"
     9  	"crypto/x509"
    10  	"encoding/base64"
    11  	"errors"
    12  	"fmt"
    13  )
    14  
    15  // This code is borrowed from https://github.com/ory/x/blob/master/tlsx/cert.go
    16  
    17  // ErrNoCertificatesConfigured is returned when no TLS configuration was found.
    18  var ErrNoCertificatesConfigured = errors.New("no tls configuration was found")
    19  
    20  // ErrInvalidCertificateConfiguration is returned when an invalid TLS configuration was found.
    21  var ErrInvalidCertificateConfiguration = errors.New("tls configuration is invalid")
    22  
    23  // LoadCertificates returns loads a TLS LoadCertificates.
    24  // certString: Base64 encoded (without padding) string of the TLS certificate (PEM encoded) to be used for HTTP over TLS (HTTPS).
    25  // Example: certString="-----BEGIN CERTIFICATE-----\nMIIDZTCCAk2gAwIBAgIEV5xOtDANBgkqhkiG9w0BAQ0FADA0MTIwMAYDVQQDDClP..."
    26  // keyString: Base64 encoded (without padding) string of the private key (PEM encoded) to be used for HTTP over TLS (HTTPS).
    27  // Example: keyString="-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDg..."
    28  // certPath: The path to the TLS certificate (pem encoded).
    29  // Example: certPath=~/cert.pem
    30  // keyPath: The path to the TLS private key (pem encoded).
    31  // Example: keyPath=~/key.pem
    32  // certs: certs of tls.Certificate, *tls.Certificate
    33  func LoadCertificates(
    34  	certString, keyString string,
    35  	certFile, keyFile string,
    36  	certs ...any,
    37  ) ([]tls.Certificate, error) {
    38  	if certString == "" && keyString == "" && certFile == "" && keyFile == "" && len(certs) == 0 {
    39  		return nil, ErrNoCertificatesConfigured
    40  	}
    41  	if certString != "" && keyString != "" {
    42  		tlsCertBytes, err := base64.StdEncoding.DecodeString(certString)
    43  		if err != nil {
    44  			return nil, fmt.Errorf("unable to base64 decode the TLS certificate: %v", err)
    45  		}
    46  		tlsKeyBytes, err := base64.StdEncoding.DecodeString(keyString)
    47  		if err != nil {
    48  			return nil, fmt.Errorf("unable to base64 decode the TLS private key: %v", err)
    49  		}
    50  
    51  		cert, err := tls.X509KeyPair(tlsCertBytes, tlsKeyBytes)
    52  		if err != nil {
    53  			return nil, fmt.Errorf("unable to load X509 key pair: %v", err)
    54  		}
    55  		return []tls.Certificate{cert}, nil
    56  	}
    57  
    58  	if certFile != "" && keyFile != "" {
    59  		cert, err := tls.LoadX509KeyPair(certFile, keyFile)
    60  		if err != nil {
    61  			return nil, fmt.Errorf("unable to load X509 key pair from files: %v", err)
    62  		}
    63  		return []tls.Certificate{cert}, nil
    64  	}
    65  	var uniformedCerts []tls.Certificate
    66  	for _, cert := range of(certs...) {
    67  		switch cert.(type) {
    68  		case *tls.Certificate:
    69  			tlsCert := cert.(*tls.Certificate)
    70  			uniformedCerts = append(uniformedCerts, *tlsCert)
    71  		case tls.Certificate:
    72  			tlsCert := cert.(tls.Certificate)
    73  			uniformedCerts = append(uniformedCerts, tlsCert)
    74  		default:
    75  			return nil, fmt.Errorf("unable to load X509 key pair from cert: %v", cert)
    76  		}
    77  	}
    78  
    79  	return nil, ErrInvalidCertificateConfiguration
    80  }
    81  
    82  // LoadX509Certificates returns loads a TLS LoadCertificates of x509.
    83  func LoadX509Certificates(
    84  	certString, keyString string,
    85  	certFile, keyFile string,
    86  ) ([]*x509.Certificate, error) {
    87  	certs, err := LoadCertificates(certString, keyString, certFile, keyFile)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	var x509Certs []*x509.Certificate
    92  	for _, cert := range certs {
    93  		for _, certBytes := range cert.Certificate {
    94  			x509Cert, err := x509.ParseCertificate(certBytes)
    95  			if err != nil {
    96  				return nil, err
    97  			}
    98  			x509Certs = append(x509Certs, x509Cert)
    99  		}
   100  	}
   101  	if len(x509Certs) == 0 {
   102  		return nil, ErrNoCertificatesConfigured
   103  	}
   104  	return x509Certs, nil
   105  }
   106  
   107  func LoadCertificateAndPool(
   108  	certPool *x509.CertPool,
   109  	certString, keyString string,
   110  	certFile, keyFile string,
   111  ) ([]tls.Certificate, *x509.CertPool, error) {
   112  	certs, err := LoadCertificates(certString, keyString, certFile, keyFile)
   113  	if err != nil {
   114  		return nil, nil, err
   115  	}
   116  	certPool, err = LoadX509CertificatePool(certPool, "", "", certs)
   117  	if err != nil {
   118  		return nil, nil, err
   119  	}
   120  	return certs, certPool, nil
   121  
   122  }