github.com/metacubex/mihomo@v1.18.5/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 }