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