github.com/sagernet/sing-box@v1.9.0-rc.20/common/tls/mkcert.go (about)

     1  package tls
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/tls"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/pem"
    10  	"math/big"
    11  	"time"
    12  )
    13  
    14  func GenerateCertificate(timeFunc func() time.Time, serverName string) (*tls.Certificate, error) {
    15  	privateKeyPem, publicKeyPem, err := GenerateKeyPair(timeFunc, serverName, timeFunc().Add(time.Hour))
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  	certificate, err := tls.X509KeyPair(publicKeyPem, privateKeyPem)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	return &certificate, err
    24  }
    25  
    26  func GenerateKeyPair(timeFunc func() time.Time, serverName string, expire time.Time) (privateKeyPem []byte, publicKeyPem []byte, err error) {
    27  	if timeFunc == nil {
    28  		timeFunc = time.Now
    29  	}
    30  	key, err := rsa.GenerateKey(rand.Reader, 2048)
    31  	if err != nil {
    32  		return
    33  	}
    34  	serialNumber, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
    35  	if err != nil {
    36  		return
    37  	}
    38  	template := &x509.Certificate{
    39  		SerialNumber:          serialNumber,
    40  		NotBefore:             timeFunc().Add(time.Hour * -1),
    41  		NotAfter:              expire,
    42  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    43  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
    44  		BasicConstraintsValid: true,
    45  		Subject: pkix.Name{
    46  			CommonName: serverName,
    47  		},
    48  		DNSNames: []string{serverName},
    49  	}
    50  	publicDer, err := x509.CreateCertificate(rand.Reader, template, template, key.Public(), key)
    51  	if err != nil {
    52  		return
    53  	}
    54  	privateDer, err := x509.MarshalPKCS8PrivateKey(key)
    55  	if err != nil {
    56  		return
    57  	}
    58  	publicKeyPem = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: publicDer})
    59  	privateKeyPem = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privateDer})
    60  	return
    61  }