go_study/fabric-main/internal/pkg/comm/testdata/certs/generate.go

308 lines
8.3 KiB
Go

/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
// +build ignore
//go:generate -command gencerts go run ./generate.go
//go:generate gencerts -orgs 2 -child-orgs 2 -servers 2 -clients 2
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"math/big"
"net"
"os"
"time"
)
// command line flags
var (
numOrgs = flag.Int("orgs", 2, "number of unique organizations")
numChildOrgs = flag.Int("child-orgs", 2, "number of intermediaries per organization")
numClientCerts = flag.Int("clients", 1, "number of client certificates per organization")
numServerCerts = flag.Int("servers", 1, "number of server certificates per organization")
)
// default template for X509 subject
func subjectTemplate() pkix.Name {
return pkix.Name{
Country: []string{"US"},
Locality: []string{"San Francisco"},
Province: []string{"California"},
}
}
// default template for X509 certificates
func x509Template() (x509.Certificate, error) {
// generate a serial number
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return x509.Certificate{}, err
}
now := time.Now()
// basic template to use
x509 := x509.Certificate{
SerialNumber: serialNumber,
NotBefore: now,
NotAfter: now.Add(3650 * 24 * time.Hour), //~ten years
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
BasicConstraintsValid: true,
}
return x509, nil
}
// generate an EC private key (P256 curve)
func genKeyECDSA(name string) (*ecdsa.PrivateKey, error) {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
// write key out to file
keyBytes, err := x509.MarshalECPrivateKey(priv)
if err != nil {
return nil, err
}
keyFile, err := os.OpenFile(name+"-key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
if err != nil {
return nil, err
}
defer keyFile.Close()
err = pem.Encode(keyFile, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes})
if err != nil {
return nil, err
}
return priv, nil
}
// generate a signed X509 certficate using ECDSA
func genCertificateECDSA(
name string,
template, parent *x509.Certificate,
pub *ecdsa.PublicKey, priv *ecdsa.PrivateKey,
) (*x509.Certificate, error) {
// create the x509 public cert
certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, pub, priv)
if err != nil {
return nil, err
}
x509Cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
// write cert out to file
certFile, err := os.Create(name + "-cert.pem")
if err != nil {
return nil, err
}
defer certFile.Close()
// pem encode the cert
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
if err != nil {
return nil, err
}
return x509Cert, nil
}
// generate an EC certificate appropriate for use by a TLS server
func genServerCertificateECDSA(name string, signKey *ecdsa.PrivateKey, signCert *x509.Certificate) error {
fmt.Println(name)
key, err := genKeyECDSA(name)
if err != nil {
return err
}
template, err := x509Template()
if err != nil {
return err
}
template.ExtKeyUsage = []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
}
// set the organization for the subject
subject := subjectTemplate()
subject.Organization = []string{name}
subject.CommonName = "localhost"
template.Subject = subject
template.DNSNames = []string{"localhost"}
template.IPAddresses = []net.IP{
net.ParseIP("127.0.0.1"),
net.ParseIP("::1"),
}
_, err = genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey)
if err != nil {
return err
}
return nil
}
// generate an EC certificate appropriate for use by a TLS server
func genClientCertificateECDSA(name string, signKey *ecdsa.PrivateKey, signCert *x509.Certificate) error {
fmt.Println(name)
key, err := genKeyECDSA(name)
if err != nil {
return err
}
template, err := x509Template()
if err != nil {
return err
}
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
// set the organization for the subject
subject := subjectTemplate()
subject.Organization = []string{name}
subject.CommonName = name
template.Subject = subject
_, err = genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey)
if err != nil {
return err
}
return nil
}
// generate an EC certificate signing(CA) key pair and output as
// PEM-encoded files
func genCertificateAuthorityECDSA(name string) (*ecdsa.PrivateKey, *x509.Certificate, error) {
key, err := genKeyECDSA(name)
if err != nil {
return nil, nil, err
}
template, err := x509Template()
if err != nil {
return nil, nil, err
}
// this is a CA
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
// set the organization for the subject
subject := subjectTemplate()
subject.Organization = []string{name}
subject.CommonName = name
template.Subject = subject
template.SubjectKeyId = []byte{1, 2, 3, 4}
x509Cert, err := genCertificateECDSA(name, &template, &template, &key.PublicKey, key)
if err != nil {
return nil, nil, err
}
return key, x509Cert, nil
}
// generate an EC certificate appropriate for use by a TLS server
func genIntermediateCertificateAuthorityECDSA(
name string,
signKey *ecdsa.PrivateKey,
signCert *x509.Certificate,
) (*ecdsa.PrivateKey, *x509.Certificate, error) {
fmt.Println(name)
key, err := genKeyECDSA(name)
if err != nil {
return nil, nil, err
}
template, err := x509Template()
if err != nil {
return nil, nil, err
}
// this is a CA
template.IsCA = true
template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
// set the organization for the subject
subject := subjectTemplate()
subject.Organization = []string{name}
subject.CommonName = name
template.Subject = subject
template.SubjectKeyId = []byte{1, 2, 3, 4}
x509Cert, err := genCertificateECDSA(name, &template, signCert, &key.PublicKey, signKey)
if err != nil {
return nil, nil, err
}
return key, x509Cert, nil
}
const baseOrgName = "Org"
func main() {
flag.Parse()
fmt.Printf("Generating %d organizations each with %d server(s) and %d client(s)\n", *numOrgs, *numServerCerts, *numClientCerts)
// generate orgs / CAs
for i := 1; i <= *numOrgs; i++ {
signKey, signCert, err := genCertificateAuthorityECDSA(fmt.Sprintf(baseOrgName+"%d", i))
if err != nil {
fmt.Printf("error generating CA %s%d : %s\n", baseOrgName, i, err.Error())
}
// generate server certificates for the org
for j := 1; j <= *numServerCerts; j++ {
name := fmt.Sprintf(baseOrgName+"%d-server%d", i, j)
if err := genServerCertificateECDSA(name, signKey, signCert); err != nil {
fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error())
}
}
// generate client certificates for the org
for k := 1; k <= *numClientCerts; k++ {
name := fmt.Sprintf(baseOrgName+"%d-client%d", i, k)
if err := genClientCertificateECDSA(name, signKey, signCert); err != nil {
fmt.Printf("error generating client certificate for %s: %s\n", name, err.Error())
}
}
// generate child orgs (intermediary authorities)
for m := 1; m <= *numChildOrgs; m++ {
name := fmt.Sprintf(baseOrgName+"%d-child%d", i, m)
childSignKey, childSignCert, err := genIntermediateCertificateAuthorityECDSA(name, signKey, signCert)
if err != nil {
fmt.Printf("error generating CA %s: %s\n", name, err.Error())
}
// generate server certificates for the child org
for n := 1; n <= *numServerCerts; n++ {
name := fmt.Sprintf(baseOrgName+"%d-child%d-server%d", i, m, n)
if err := genServerCertificateECDSA(name, childSignKey, childSignCert); err != nil {
fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error())
}
}
// generate client certificates for the child org
for p := 1; p <= *numClientCerts; p++ {
name := fmt.Sprintf(baseOrgName+"%d-child%d-client%d", i, m, p)
if err := genClientCertificateECDSA(name, childSignKey, childSignCert); err != nil {
fmt.Printf("error generating server certificate for %s: %s\n", name, err.Error())
}
}
}
}
}