github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/gmtls/generate_cert.go (about)

     1  // Copyright 2022 s1ren@github.com/hxx258456.
     2  
     3  //go:build ignore
     4  // +build ignore
     5  
     6  /*
     7  gmtls是基于`golang/go`的`tls`包实现的国密改造版本。
     8  对应版权声明: thrid_licenses/github.com/golang/go/LICENSE
     9  */
    10  
    11  // Generate a self-signed X.509 certificate for a TLS server. Outputs to
    12  // 'cert.pem' and 'key.pem' and will overwrite existing files.
    13  
    14  package main
    15  
    16  import (
    17  	"crypto/ecdsa"
    18  	"crypto/ed25519"
    19  	"crypto/elliptic"
    20  	"crypto/rand"
    21  	"crypto/rsa"
    22  	"crypto/x509/pkix"
    23  	"encoding/pem"
    24  	"flag"
    25  	"log"
    26  	"math/big"
    27  	"net"
    28  	"os"
    29  	"strings"
    30  	"time"
    31  
    32  	"github.com/hxx258456/ccgo/sm2"
    33  	"github.com/hxx258456/ccgo/x509"
    34  )
    35  
    36  var (
    37  	host       = flag.String("host", "", "Comma-separated hostnames and IPs to generate a certificate for")
    38  	validFrom  = flag.String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011")
    39  	validFor   = flag.Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for")
    40  	isCA       = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
    41  	rsaBits    = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
    42  	ecCurve    = flag.String("ec-curve", "", "EC curve to use to generate a key. Valid values are SM2P256 (recommended), P224, P256, P384, P521")
    43  	ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key")
    44  )
    45  
    46  func publicKey(priv interface{}) interface{} {
    47  	switch k := priv.(type) {
    48  	case *sm2.PrivateKey:
    49  		return &k.PublicKey
    50  	case *rsa.PrivateKey:
    51  		return &k.PublicKey
    52  	case *ecdsa.PrivateKey:
    53  		return &k.PublicKey
    54  	case ed25519.PrivateKey:
    55  		return k.Public().(ed25519.PublicKey)
    56  	default:
    57  		return nil
    58  	}
    59  }
    60  
    61  func main() {
    62  	flag.Parse()
    63  
    64  	if len(*host) == 0 {
    65  		log.Fatalf("Missing required --host parameter")
    66  	}
    67  
    68  	var priv interface{}
    69  	var err error
    70  
    71  	switch *ecCurve {
    72  	case "":
    73  		if *ed25519Key {
    74  			_, priv, err = ed25519.GenerateKey(rand.Reader)
    75  		} else {
    76  			priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
    77  		}
    78  	case "SM2P256":
    79  		priv, err = sm2.GenerateKey(rand.Reader)
    80  	case "P224":
    81  		priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
    82  	case "P256":
    83  		priv, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    84  	case "P384":
    85  		priv, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
    86  	case "P521":
    87  		priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
    88  	default:
    89  		log.Fatalf("Unrecognized elliptic curve: %q", *ecCurve)
    90  	}
    91  	if err != nil {
    92  		log.Fatalf("Failed to generate private key: %v", err)
    93  	}
    94  
    95  	// ECDSA, ED25519 and RSA subject keys should have the DigitalSignature
    96  	// KeyUsage bits set in the x509.Certificate template
    97  	keyUsage := x509.KeyUsageDigitalSignature
    98  	// Only RSA subject keys should have the KeyEncipherment KeyUsage bits set. In
    99  	// the context of TLS this KeyUsage is particular to RSA key exchange and
   100  	// authentication.
   101  	if _, isRSA := priv.(*rsa.PrivateKey); isRSA {
   102  		keyUsage |= x509.KeyUsageKeyEncipherment
   103  	}
   104  
   105  	var notBefore time.Time
   106  	if len(*validFrom) == 0 {
   107  		notBefore = time.Now()
   108  	} else {
   109  		notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
   110  		if err != nil {
   111  			log.Fatalf("Failed to parse creation date: %v", err)
   112  		}
   113  	}
   114  
   115  	notAfter := notBefore.Add(*validFor)
   116  
   117  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
   118  	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
   119  	if err != nil {
   120  		log.Fatalf("Failed to generate serial number: %v", err)
   121  	}
   122  
   123  	template := x509.Certificate{
   124  		SerialNumber: serialNumber,
   125  		Subject: pkix.Name{
   126  			Organization: []string{"Acme Co"},
   127  		},
   128  		NotBefore: notBefore,
   129  		NotAfter:  notAfter,
   130  
   131  		KeyUsage:              keyUsage,
   132  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
   133  		BasicConstraintsValid: true,
   134  	}
   135  
   136  	hosts := strings.Split(*host, ",")
   137  	for _, h := range hosts {
   138  		if ip := net.ParseIP(h); ip != nil {
   139  			template.IPAddresses = append(template.IPAddresses, ip)
   140  		} else {
   141  			template.DNSNames = append(template.DNSNames, h)
   142  		}
   143  	}
   144  
   145  	if *isCA {
   146  		template.IsCA = true
   147  		template.KeyUsage |= x509.KeyUsageCertSign
   148  	}
   149  
   150  	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
   151  	if err != nil {
   152  		log.Fatalf("Failed to create certificate: %v", err)
   153  	}
   154  
   155  	certOut, err := os.Create("cert.pem")
   156  	if err != nil {
   157  		log.Fatalf("Failed to open cert.pem for writing: %v", err)
   158  	}
   159  	if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
   160  		log.Fatalf("Failed to write data to cert.pem: %v", err)
   161  	}
   162  	if err := certOut.Close(); err != nil {
   163  		log.Fatalf("Error closing cert.pem: %v", err)
   164  	}
   165  	log.Print("wrote cert.pem\n")
   166  
   167  	keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   168  	if err != nil {
   169  		log.Fatalf("Failed to open key.pem for writing: %v", err)
   170  		return
   171  	}
   172  	privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
   173  	if err != nil {
   174  		log.Fatalf("Unable to marshal private key: %v", err)
   175  	}
   176  	if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
   177  		log.Fatalf("Failed to write data to key.pem: %v", err)
   178  	}
   179  	if err := keyOut.Close(); err != nil {
   180  		log.Fatalf("Error closing key.pem: %v", err)
   181  	}
   182  	log.Print("wrote key.pem\n")
   183  }