github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/control/cert.go (about)

     1  package control
     2  
     3  import (
     4  	"context"
     5  	"crypto/x509"
     6  	"encoding/json"
     7  	"flag"
     8  	"os"
     9  	"strings"
    10  	"time"
    11  
    12  	"v2ray.com/core/common"
    13  	"v2ray.com/core/common/protocol/tls/cert"
    14  	"v2ray.com/core/common/task"
    15  )
    16  
    17  type stringList []string
    18  
    19  func (l *stringList) String() string {
    20  	return "String list"
    21  }
    22  
    23  func (l *stringList) Set(v string) error {
    24  	if v == "" {
    25  		return newError("empty value")
    26  	}
    27  	*l = append(*l, v)
    28  	return nil
    29  }
    30  
    31  type jsonCert struct {
    32  	Certificate []string `json:"certificate"`
    33  	Key         []string `json:"key"`
    34  }
    35  
    36  type CertificateCommand struct {
    37  }
    38  
    39  func (c *CertificateCommand) Name() string {
    40  	return "cert"
    41  }
    42  
    43  func (c *CertificateCommand) Description() Description {
    44  	return Description{
    45  		Short: "Generate TLS certificates.",
    46  		Usage: []string{
    47  			"v2ctl cert [--ca] [--domain=v2ray.com] [--expire=240h]",
    48  			"Generate new TLS certificate",
    49  			"--ca The new certificate is a CA certificate",
    50  			"--domain Common name for the certificate",
    51  			"--expire Time until certificate expires. 240h = 10 days.",
    52  		},
    53  	}
    54  }
    55  
    56  func (c *CertificateCommand) printJson(certificate *cert.Certificate) {
    57  	certPEM, keyPEM := certificate.ToPEM()
    58  	jCert := &jsonCert{
    59  		Certificate: strings.Split(strings.TrimSpace(string(certPEM)), "\n"),
    60  		Key:         strings.Split(strings.TrimSpace(string(keyPEM)), "\n"),
    61  	}
    62  	content, err := json.MarshalIndent(jCert, "", "  ")
    63  	common.Must(err)
    64  	os.Stdout.Write(content)
    65  	os.Stdout.WriteString("\n")
    66  }
    67  
    68  func (c *CertificateCommand) writeFile(content []byte, name string) error {
    69  	f, err := os.Create(name)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	defer f.Close()
    74  
    75  	return common.Error2(f.Write(content))
    76  }
    77  
    78  func (c *CertificateCommand) printFile(certificate *cert.Certificate, name string) error {
    79  	certPEM, keyPEM := certificate.ToPEM()
    80  	return task.Run(context.Background(), func() error {
    81  		return c.writeFile(certPEM, name+"_cert.pem")
    82  	}, func() error {
    83  		return c.writeFile(keyPEM, name+"_key.pem")
    84  	})
    85  }
    86  
    87  func (c *CertificateCommand) Execute(args []string) error {
    88  	fs := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
    89  
    90  	var domainNames stringList
    91  	fs.Var(&domainNames, "domain", "Domain name for the certificate")
    92  
    93  	commonName := fs.String("name", "V2Ray Inc", "The common name of this certificate")
    94  	organization := fs.String("org", "V2Ray Inc", "Organization of the certificate")
    95  
    96  	isCA := fs.Bool("ca", false, "Whether this certificate is a CA")
    97  	jsonOutput := fs.Bool("json", true, "Print certificate in JSON format")
    98  	fileOutput := fs.String("file", "", "Save certificate in file.")
    99  
   100  	expire := fs.Duration("expire", time.Hour*24*90 /* 90 days */, "Time until the certificate expires. Default value 3 months.")
   101  
   102  	if err := fs.Parse(args); err != nil {
   103  		return err
   104  	}
   105  
   106  	var opts []cert.Option
   107  	if *isCA {
   108  		opts = append(opts, cert.Authority(*isCA))
   109  		opts = append(opts, cert.KeyUsage(x509.KeyUsageCertSign|x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature))
   110  	}
   111  
   112  	opts = append(opts, cert.NotAfter(time.Now().Add(*expire)))
   113  	opts = append(opts, cert.CommonName(*commonName))
   114  	if len(domainNames) > 0 {
   115  		opts = append(opts, cert.DNSNames(domainNames...))
   116  	}
   117  	opts = append(opts, cert.Organization(*organization))
   118  
   119  	cert, err := cert.Generate(nil, opts...)
   120  	if err != nil {
   121  		return newError("failed to generate TLS certificate").Base(err)
   122  	}
   123  
   124  	if *jsonOutput {
   125  		c.printJson(cert)
   126  	}
   127  
   128  	if len(*fileOutput) > 0 {
   129  		if err := c.printFile(cert, *fileOutput); err != nil {
   130  			return err
   131  		}
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func init() {
   138  	common.Must(RegisterCommand(&CertificateCommand{}))
   139  }