github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/pkg/comm/testdata/certs/generate.go (about) 1 //go:build ignore 2 // +build ignore 3 4 /* 5 Copyright hechain. All Rights Reserved. 6 7 SPDX-License-Identifier: Apache-2.0 8 */ 9 10 //go:generate -command gencerts go run ./generate.go 11 //go:generate gencerts -orgs 2 -child-orgs 2 -servers 2 -clients 2 12 13 package main 14 15 import ( 16 "crypto/ecdsa" 17 "crypto/elliptic" 18 "crypto/rand" 19 "crypto/x509" 20 "crypto/x509/pkix" 21 "encoding/pem" 22 "flag" 23 "fmt" 24 "math/big" 25 "net" 26 "os" 27 "time" 28 ) 29 30 // command line flags 31 var ( 32 numOrgs = flag.Int("orgs", 2, "number of unique organizations") 33 numChildOrgs = flag.Int("child-orgs", 2, "number of intermediaries per organization") 34 numClientCerts = flag.Int("clients", 1, "number of client certificates per organization") 35 numServerCerts = flag.Int("servers", 1, "number of server certificates per organization") 36 ) 37 38 // default template for X509 subject 39 func subjectTemplate() pkix.Name { 40 return pkix.Name{ 41 Country: []string{"US"}, 42 Locality: []string{"San Francisco"}, 43 Province: []string{"California"}, 44 } 45 } 46 47 // default template for X509 certificates 48 func x509Template() (x509.Certificate, error) { 49 // generate a serial number 50 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 51 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 52 if err != nil { 53 return x509.Certificate{}, err 54 } 55 56 now := time.Now() 57 // basic template to use 58 x509 := x509.Certificate{ 59 SerialNumber: serialNumber, 60 NotBefore: now, 61 NotAfter: now.Add(3650 * 24 * time.Hour), //~ten years 62 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 63 BasicConstraintsValid: true, 64 } 65 return x509, nil 66 } 67 68 // generate an EC private key (P256 curve) 69 func genKeyECDSA(name string) (*ecdsa.PrivateKey, error) { 70 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 71 if err != nil { 72 return nil, err 73 } 74 // write key out to file 75 keyBytes, err := x509.MarshalECPrivateKey(priv) 76 if err != nil { 77 return nil, err 78 } 79 keyFile, err := os.OpenFile(name+"-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) 80 if err != nil { 81 return nil, err 82 } 83 defer keyFile.Close() 84 err = pem.Encode(keyFile, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes}) 85 if err != nil { 86 return nil, err 87 } 88 return priv, nil 89 } 90 91 // generate a signed X509 certficate using ECDSA 92 func genCertificateECDSA( 93 name string, 94 template, parent *x509.Certificate, 95 pub *ecdsa.PublicKey, priv *ecdsa.PrivateKey, 96 ) (*x509.Certificate, error) { 97 // create the x509 public cert 98 certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, pub, priv) 99 if err != nil { 100 return nil, err 101 } 102 x509Cert, err := x509.ParseCertificate(certBytes) 103 if err != nil { 104 return nil, err 105 } 106 107 // write cert out to file 108 certFile, err := os.Create(name + "-cert.pem") 109 if err != nil { 110 return nil, err 111 } 112 defer certFile.Close() 113 114 // pem encode the cert 115 err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}) 116 if err != nil { 117 return nil, err 118 } 119 120 return x509Cert, nil 121 } 122 123 // generate an EC certificate appropriate for use by a TLS server 124 func genServerCertificateECDSA(name string, signKey *ecdsa.PrivateKey, signCert *x509.Certificate) error { 125 fmt.Println(name) 126 127 key, err := genKeyECDSA(name) 128 if err != nil { 129 return err 130 } 131 template, err := x509Template() 132 if err != nil { 133 return err 134 } 135 136 template.ExtKeyUsage = []x509.ExtKeyUsage{ 137 x509.ExtKeyUsageServerAuth, 138 x509.ExtKeyUsageClientAuth, 139 } 140 141 // set the organization for the subject 142 subject := subjectTemplate() 143 subject.Organization = []string{name} 144 subject.CommonName = "localhost" 145 146 template.Subject = subject 147 template.DNSNames = []string{"localhost"} 148 template.IPAddresses = []net.IP{ 149 net.ParseIP("127.0.0.1"), 150 net.ParseIP("::1"), 151 } 152 153 _, err = genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey) 154 if err != nil { 155 return err 156 } 157 158 return nil 159 } 160 161 // generate an EC certificate appropriate for use by a TLS server 162 func genClientCertificateECDSA(name string, signKey *ecdsa.PrivateKey, signCert *x509.Certificate) error { 163 fmt.Println(name) 164 165 key, err := genKeyECDSA(name) 166 if err != nil { 167 return err 168 } 169 template, err := x509Template() 170 if err != nil { 171 return err 172 } 173 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} 174 175 // set the organization for the subject 176 subject := subjectTemplate() 177 subject.Organization = []string{name} 178 subject.CommonName = name 179 template.Subject = subject 180 181 _, err = genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey) 182 if err != nil { 183 return err 184 } 185 186 return nil 187 } 188 189 // generate an EC certificate signing(CA) key pair and output as 190 // PEM-encoded files 191 func genCertificateAuthorityECDSA(name string) (*ecdsa.PrivateKey, *x509.Certificate, error) { 192 key, err := genKeyECDSA(name) 193 if err != nil { 194 return nil, nil, err 195 } 196 template, err := x509Template() 197 if err != nil { 198 return nil, nil, err 199 } 200 201 // this is a CA 202 template.IsCA = true 203 template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign 204 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} 205 206 // set the organization for the subject 207 subject := subjectTemplate() 208 subject.Organization = []string{name} 209 subject.CommonName = name 210 211 template.Subject = subject 212 template.SubjectKeyId = []byte{1, 2, 3, 4} 213 214 x509Cert, err := genCertificateECDSA(name, &template, &template, &key.PublicKey, key) 215 if err != nil { 216 return nil, nil, err 217 } 218 return key, x509Cert, nil 219 } 220 221 // generate an EC certificate appropriate for use by a TLS server 222 func genIntermediateCertificateAuthorityECDSA( 223 name string, 224 signKey *ecdsa.PrivateKey, 225 signCert *x509.Certificate, 226 ) (*ecdsa.PrivateKey, *x509.Certificate, error) { 227 fmt.Println(name) 228 229 key, err := genKeyECDSA(name) 230 if err != nil { 231 return nil, nil, err 232 } 233 template, err := x509Template() 234 if err != nil { 235 return nil, nil, err 236 } 237 238 // this is a CA 239 template.IsCA = true 240 template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign 241 template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} 242 243 // set the organization for the subject 244 subject := subjectTemplate() 245 subject.Organization = []string{name} 246 subject.CommonName = name 247 248 template.Subject = subject 249 template.SubjectKeyId = []byte{1, 2, 3, 4} 250 251 x509Cert, err := genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey) 252 if err != nil { 253 return nil, nil, err 254 } 255 256 return key, x509Cert, nil 257 } 258 259 const baseOrgName = "Org" 260 261 func main() { 262 flag.Parse() 263 fmt.Printf("Generating %d organizations each with %d server(s) and %d client(s)\n", *numOrgs, *numServerCerts, *numClientCerts) 264 265 // generate orgs / CAs 266 for i := 1; i <= *numOrgs; i++ { 267 signKey, signCert, err := genCertificateAuthorityECDSA(fmt.Sprintf(baseOrgName+"%d", i)) 268 if err != nil { 269 fmt.Printf("error generating CA %s%d : %s\n", baseOrgName, i, err.Error()) 270 } 271 // generate server certificates for the org 272 for j := 1; j <= *numServerCerts; j++ { 273 name := fmt.Sprintf(baseOrgName+"%d-server%d", i, j) 274 if err := genServerCertificateECDSA(name, signKey, signCert); err != nil { 275 fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error()) 276 } 277 } 278 // generate client certificates for the org 279 for k := 1; k <= *numClientCerts; k++ { 280 name := fmt.Sprintf(baseOrgName+"%d-client%d", i, k) 281 if err := genClientCertificateECDSA(name, signKey, signCert); err != nil { 282 fmt.Printf("error generating client certificate for %s: %s\n", name, err.Error()) 283 } 284 } 285 // generate child orgs (intermediary authorities) 286 for m := 1; m <= *numChildOrgs; m++ { 287 name := fmt.Sprintf(baseOrgName+"%d-child%d", i, m) 288 childSignKey, childSignCert, err := genIntermediateCertificateAuthorityECDSA(name, signKey, signCert) 289 if err != nil { 290 fmt.Printf("error generating CA %s: %s\n", name, err.Error()) 291 } 292 // generate server certificates for the child org 293 for n := 1; n <= *numServerCerts; n++ { 294 name := fmt.Sprintf(baseOrgName+"%d-child%d-server%d", i, m, n) 295 if err := genServerCertificateECDSA(name, childSignKey, childSignCert); err != nil { 296 fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error()) 297 } 298 } 299 // generate client certificates for the child org 300 for p := 1; p <= *numClientCerts; p++ { 301 name := fmt.Sprintf(baseOrgName+"%d-child%d-client%d", i, m, p) 302 if err := genClientCertificateECDSA(name, childSignKey, childSignCert); err != nil { 303 fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error()) 304 } 305 } 306 } 307 } 308 }