github.com/kelleygo/clashcore@v1.0.2/common/net/tls.go (about)

     1  package net
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/tls"
     7  	"crypto/x509"
     8  	"encoding/pem"
     9  	"fmt"
    10  	"math/big"
    11  )
    12  
    13  type Path interface {
    14  	Resolve(path string) string
    15  }
    16  
    17  func ParseCert(certificate, privateKey string, path Path) (tls.Certificate, error) {
    18  	if certificate == "" && privateKey == "" {
    19  		return newRandomTLSKeyPair()
    20  	}
    21  	cert, painTextErr := tls.X509KeyPair([]byte(certificate), []byte(privateKey))
    22  	if painTextErr == nil {
    23  		return cert, nil
    24  	}
    25  
    26  	certificate = path.Resolve(certificate)
    27  	privateKey = path.Resolve(privateKey)
    28  	cert, loadErr := tls.LoadX509KeyPair(certificate, privateKey)
    29  	if loadErr != nil {
    30  		return tls.Certificate{}, fmt.Errorf("parse certificate failed, maybe format error:%s, or path error: %s", painTextErr.Error(), loadErr.Error())
    31  	}
    32  	return cert, nil
    33  }
    34  
    35  func newRandomTLSKeyPair() (tls.Certificate, error) {
    36  	key, err := rsa.GenerateKey(rand.Reader, 2048)
    37  	if err != nil {
    38  		return tls.Certificate{}, err
    39  	}
    40  	template := x509.Certificate{SerialNumber: big.NewInt(1)}
    41  	certDER, err := x509.CreateCertificate(
    42  		rand.Reader,
    43  		&template,
    44  		&template,
    45  		&key.PublicKey,
    46  		key)
    47  	if err != nil {
    48  		return tls.Certificate{}, err
    49  	}
    50  	keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
    51  	certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
    52  
    53  	tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
    54  	if err != nil {
    55  		return tls.Certificate{}, err
    56  	}
    57  	return tlsCert, nil
    58  }