github.com/hyperledger-labs/bdls@v2.1.1+incompatible/common/crypto/tlsgen/key.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tlsgen
     8  
     9  import (
    10  	"crypto"
    11  	"crypto/ecdsa"
    12  	"crypto/elliptic"
    13  	"crypto/rand"
    14  	"crypto/x509"
    15  	"crypto/x509/pkix"
    16  	"encoding/pem"
    17  	"math/big"
    18  	"net"
    19  	"time"
    20  
    21  	"github.com/pkg/errors"
    22  )
    23  
    24  func newPrivKey() (*ecdsa.PrivateKey, []byte, error) {
    25  	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    26  	if err != nil {
    27  		return nil, nil, err
    28  	}
    29  	privBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
    30  	if err != nil {
    31  		return nil, nil, err
    32  	}
    33  	return privateKey, privBytes, nil
    34  }
    35  
    36  func newCertTemplate() (x509.Certificate, error) {
    37  	sn, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
    38  	if err != nil {
    39  		return x509.Certificate{}, err
    40  	}
    41  	return x509.Certificate{
    42  		Subject:      pkix.Name{SerialNumber: sn.String()},
    43  		NotBefore:    time.Now().Add(time.Hour * (-24)),
    44  		NotAfter:     time.Now().Add(time.Hour * 24),
    45  		KeyUsage:     x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
    46  		SerialNumber: sn,
    47  	}, nil
    48  }
    49  
    50  func newCertKeyPair(isCA bool, isServer bool, host string, certSigner crypto.Signer, parent *x509.Certificate) (*CertKeyPair, error) {
    51  	privateKey, privBytes, err := newPrivKey()
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	template, err := newCertTemplate()
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	tenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 10)
    62  	if isCA {
    63  		template.NotAfter = tenYearsFromNow
    64  		template.IsCA = true
    65  		template.KeyUsage |= x509.KeyUsageCertSign | x509.KeyUsageCRLSign
    66  		template.ExtKeyUsage = []x509.ExtKeyUsage{
    67  			x509.ExtKeyUsageClientAuth,
    68  			x509.ExtKeyUsageServerAuth,
    69  		}
    70  		template.BasicConstraintsValid = true
    71  	} else {
    72  		template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
    73  	}
    74  	if isServer {
    75  		template.NotAfter = tenYearsFromNow
    76  		template.ExtKeyUsage = append(template.ExtKeyUsage, x509.ExtKeyUsageServerAuth)
    77  		if ip := net.ParseIP(host); ip != nil {
    78  			template.IPAddresses = append(template.IPAddresses, ip)
    79  		} else {
    80  			template.DNSNames = append(template.DNSNames, host)
    81  		}
    82  	}
    83  	// If no parent cert, it's a self signed cert
    84  	if parent == nil || certSigner == nil {
    85  		parent = &template
    86  		certSigner = privateKey
    87  	}
    88  	rawBytes, err := x509.CreateCertificate(rand.Reader, &template, parent, &privateKey.PublicKey, certSigner)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	pubKey := encodePEM("CERTIFICATE", rawBytes)
    93  
    94  	block, _ := pem.Decode(pubKey)
    95  	if block == nil { // Never comes unless x509 or pem has bug
    96  		return nil, errors.Errorf("%s: wrong PEM encoding", pubKey)
    97  	}
    98  	cert, err := x509.ParseCertificate(block.Bytes)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	privKey := encodePEM("EC PRIVATE KEY", privBytes)
   103  	return &CertKeyPair{
   104  		Key:     privKey,
   105  		Cert:    pubKey,
   106  		Signer:  privateKey,
   107  		TLSCert: cert,
   108  	}, nil
   109  }
   110  
   111  func encodePEM(keyType string, data []byte) []byte {
   112  	return pem.EncodeToMemory(&pem.Block{Type: keyType, Bytes: data})
   113  }