github.com/codingeasygo/util@v0.0.0-20231206062002-1ce2f004b7d9/xcrypto/xcrypto.go (about)

     1  package xcrypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"crypto/x509/pkix"
    10  	"encoding/pem"
    11  	"io/ioutil"
    12  	"math/big"
    13  	"net"
    14  	"strings"
    15  	"time"
    16  )
    17  
    18  func generateRSA(isCA bool, template, parent *x509.Certificate, rootKey *rsa.PrivateKey, commonName string, dnsNames []string, ipAddresses []net.IP, bits int) (cert *x509.Certificate, privKey *rsa.PrivateKey, certPEM, privPEM []byte, err error) {
    19  	privKey, err = rsa.GenerateKey(rand.Reader, bits)
    20  	if err != nil {
    21  		return
    22  	}
    23  
    24  	if parent == nil {
    25  		parent = template
    26  	}
    27  	if rootKey == nil {
    28  		rootKey = privKey
    29  	}
    30  	certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, &privKey.PublicKey, rootKey)
    31  	if err != nil {
    32  		return
    33  	}
    34  	cert, err = x509.ParseCertificate(certBytes)
    35  	if err != nil {
    36  		return
    37  	}
    38  
    39  	certBuffer := &bytes.Buffer{}
    40  	certBlock := &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}
    41  	pem.Encode(certBuffer, certBlock)
    42  	certPEM = certBuffer.Bytes()
    43  
    44  	privBuffer := &bytes.Buffer{}
    45  	privBlock := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privKey)}
    46  	pem.Encode(privBuffer, privBlock)
    47  	privPEM = privBuffer.Bytes()
    48  	return
    49  }
    50  
    51  func GenerateRootCA(org []string, name string, bits int) (cert *x509.Certificate, privKey *rsa.PrivateKey, certPEM, privPEM []byte, err error) {
    52  	template := &x509.Certificate{
    53  		SerialNumber: big.NewInt(1),
    54  		Subject: pkix.Name{
    55  			Organization: org,
    56  			CommonName:   name,
    57  		},
    58  		NotBefore:             time.Now(),
    59  		NotAfter:              time.Now().Add(time.Hour * 24 * 365 * 10),
    60  		KeyUsage:              x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
    61  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
    62  		BasicConstraintsValid: true,
    63  		IsCA:                  true,
    64  		MaxPathLen:            2,
    65  	}
    66  	cert, privKey, certPEM, privPEM, err = generateRSA(true, template, nil, nil, name, nil, nil, bits)
    67  	return
    68  }
    69  
    70  // func GenerateDistCA(parent *x509.Certificate, rootKey *rsa.PrivateKey, name string, bits int) (cert *x509.Certificate, privKey *rsa.PrivateKey, certPEM, privPEM []byte, err error) {
    71  // 	cert, privKey, certPEM, privPEM, err = generateRSA(true, parent, rootKey, name, nil, nil, bits)
    72  // 	return
    73  // }
    74  
    75  func GenerateCert(parent *x509.Certificate, rootKey *rsa.PrivateKey, ext []x509.ExtKeyUsage, org []string, commonName string, dnsNames []string, ipAddresses []net.IP, bits int) (cert *x509.Certificate, privKey *rsa.PrivateKey, certPEM, privPEM []byte, err error) {
    76  	template := &x509.Certificate{
    77  		SerialNumber: big.NewInt(1),
    78  		Subject: pkix.Name{
    79  			Organization: org,
    80  			CommonName:   commonName,
    81  		},
    82  		NotBefore:             time.Now(),
    83  		NotAfter:              time.Now().Add(time.Hour * 24 * 365 * 10),
    84  		KeyUsage:              x509.KeyUsageDigitalSignature,
    85  		ExtKeyUsage:           ext,
    86  		BasicConstraintsValid: true,
    87  		IsCA:                  false,
    88  		DNSNames:              dnsNames,
    89  		IPAddresses:           ipAddresses,
    90  	}
    91  	cert, privKey, certPEM, privPEM, err = generateRSA(false, template, parent, rootKey, commonName, dnsNames, ipAddresses, bits)
    92  	return
    93  }
    94  
    95  // GenerateWeb will generate web cert
    96  func GenerateWeb(parent *x509.Certificate, rootKey *rsa.PrivateKey, client bool, org, domain, ip string, bits int) (cert tls.Certificate, certPEM, privPEM []byte, err error) {
    97  	domains := strings.Split(domain, ",")
    98  	ipAddress := []net.IP{}
    99  	if len(ip) > 0 {
   100  		ips := strings.Split(ip, ",")
   101  		for _, v := range ips {
   102  			ipAddress = append(ipAddress, net.ParseIP(v))
   103  		}
   104  	}
   105  	keyUsage := []x509.ExtKeyUsage{}
   106  	if client {
   107  		keyUsage = append(keyUsage, x509.ExtKeyUsageClientAuth)
   108  	} else {
   109  		keyUsage = append(keyUsage, x509.ExtKeyUsageServerAuth)
   110  	}
   111  	_, _, certPEM, privPEM, err = GenerateCert(parent, rootKey, keyUsage, []string{org}, domain, domains, ipAddress, bits)
   112  	if err == nil {
   113  		cert, err = tls.X509KeyPair(certPEM, privPEM)
   114  	}
   115  	return
   116  }
   117  
   118  func GenerateWebServerClient(org string, ca, domain, ip string, bits int) (
   119  	rootCert *x509.Certificate, rootKey *rsa.PrivateKey, rootCertPEM, rootKeyPEM []byte,
   120  	server tls.Certificate, serverCertPEM, serverKeyPEM []byte,
   121  	client tls.Certificate, clientCertPEM, clientKeyPEM []byte,
   122  	err error,
   123  ) {
   124  	rootCert, rootKey, rootCertPEM, rootKeyPEM, err = GenerateRootCA([]string{org}, ca, bits)
   125  	if err != nil {
   126  		return
   127  	}
   128  	server, serverCertPEM, serverKeyPEM, err = GenerateWeb(rootCert, rootKey, false, org, domain, ip, bits)
   129  	if err != nil {
   130  		return
   131  	}
   132  	client, clientCertPEM, clientKeyPEM, err = GenerateWeb(rootCert, rootKey, true, org, domain, ip, bits)
   133  	return
   134  }
   135  
   136  func LoadX509KeyPair(certFile, keyFile string) (cert *x509.Certificate, priv *rsa.PrivateKey, err error) {
   137  	certPEM, err := ioutil.ReadFile(certFile)
   138  	if err != nil {
   139  		return
   140  	}
   141  	keyPEM, err := ioutil.ReadFile(keyFile)
   142  	if err != nil {
   143  		return
   144  	}
   145  	//
   146  	certBlock, _ := pem.Decode(certPEM)
   147  	keyBlock, _ := pem.Decode(keyPEM)
   148  	cert, err = x509.ParseCertificate(certBlock.Bytes)
   149  	if err == nil {
   150  		priv, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
   151  	}
   152  	return
   153  }