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 }