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  }