github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/crypto/tlsgen/key.go (about)

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