cert.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package tls
  2. import (
  3. "context"
  4. "crypto/x509"
  5. "encoding/json"
  6. "os"
  7. "strings"
  8. "time"
  9. "github.com/xtls/xray-core/common"
  10. "github.com/xtls/xray-core/common/protocol/tls/cert"
  11. "github.com/xtls/xray-core/common/task"
  12. "github.com/xtls/xray-core/main/commands/base"
  13. )
  14. // cmdCert is the tls cert command
  15. var cmdCert = &base.Command{
  16. UsageLine: "{{.Exec}} tls cert [--ca] [--domain=example.com] [--expire=240h]",
  17. Short: "Generate TLS certificates",
  18. Long: `
  19. Generate TLS certificates.
  20. Arguments:
  21. -domain=domain_name
  22. The domain name for the certificate.
  23. -name=common_name
  24. The common name for the certificate.
  25. -org=organization
  26. The organization name for the certificate.
  27. -ca
  28. Whether this certificate is a CA
  29. -json
  30. The output of certificate to JSON
  31. -file
  32. The certificate path to save.
  33. -expire
  34. Expire time of the certificate. Default value 3 months.
  35. `,
  36. }
  37. func init() {
  38. cmdCert.Run = executeCert // break init loop
  39. }
  40. var (
  41. certDomainNames stringList
  42. _ = func() bool {
  43. cmdCert.Flag.Var(&certDomainNames, "domain", "Domain name for the certificate")
  44. return true
  45. }()
  46. certCommonName = cmdCert.Flag.String("name", "Xray Inc", "The common name of this certificate")
  47. certOrganization = cmdCert.Flag.String("org", "Xray Inc", "Organization of the certificate")
  48. certIsCA = cmdCert.Flag.Bool("ca", false, "Whether this certificate is a CA")
  49. certJSONOutput = cmdCert.Flag.Bool("json", true, "Print certificate in JSON format")
  50. certFileOutput = cmdCert.Flag.String("file", "", "Save certificate in file.")
  51. certExpire = cmdCert.Flag.Duration("expire", time.Hour*24*90 /* 90 days */, "Time until the certificate expires. Default value 3 months.")
  52. )
  53. func executeCert(cmd *base.Command, args []string) {
  54. var opts []cert.Option
  55. if *certIsCA {
  56. opts = append(opts, cert.Authority(*certIsCA))
  57. opts = append(opts, cert.KeyUsage(x509.KeyUsageCertSign|x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature))
  58. }
  59. opts = append(opts, cert.NotAfter(time.Now().Add(*certExpire)))
  60. opts = append(opts, cert.CommonName(*certCommonName))
  61. if len(certDomainNames) > 0 {
  62. opts = append(opts, cert.DNSNames(certDomainNames...))
  63. }
  64. opts = append(opts, cert.Organization(*certOrganization))
  65. cert, err := cert.Generate(nil, opts...)
  66. if err != nil {
  67. base.Fatalf("failed to generate TLS certificate: %s", err)
  68. }
  69. if *certJSONOutput {
  70. printJSON(cert)
  71. }
  72. if len(*certFileOutput) > 0 {
  73. if err := printFile(cert, *certFileOutput); err != nil {
  74. base.Fatalf("failed to save file: %s", err)
  75. }
  76. }
  77. }
  78. func printJSON(certificate *cert.Certificate) {
  79. certPEM, keyPEM := certificate.ToPEM()
  80. jCert := &jsonCert{
  81. Certificate: strings.Split(strings.TrimSpace(string(certPEM)), "\n"),
  82. Key: strings.Split(strings.TrimSpace(string(keyPEM)), "\n"),
  83. }
  84. content, err := json.MarshalIndent(jCert, "", " ")
  85. common.Must(err)
  86. os.Stdout.Write(content)
  87. os.Stdout.WriteString("\n")
  88. }
  89. func writeFile(content []byte, name string) error {
  90. f, err := os.Create(name)
  91. if err != nil {
  92. return err
  93. }
  94. defer f.Close()
  95. return common.Error2(f.Write(content))
  96. }
  97. func printFile(certificate *cert.Certificate, name string) error {
  98. certPEM, keyPEM := certificate.ToPEM()
  99. return task.Run(context.Background(), func() error {
  100. return writeFile(certPEM, name+"_cert.pem")
  101. }, func() error {
  102. return writeFile(keyPEM, name+"_key.pem")
  103. })
  104. }
  105. type stringList []string
  106. func (l *stringList) String() string {
  107. return "String list"
  108. }
  109. func (l *stringList) Set(v string) error {
  110. if v == "" {
  111. base.Fatalf("empty value")
  112. }
  113. *l = append(*l, v)
  114. return nil
  115. }
  116. type jsonCert struct {
  117. Certificate []string `json:"certificate"`
  118. Key []string `json:"key"`
  119. }