github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/cert/cert.go (about)

     1  package cert
     2  
     3  import (
     4  	"bytes"
     5  	cryptorand "crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"crypto/x509/pkix"
     9  	"encoding/pem"
    10  	"io/ioutil"
    11  	"math/big"
    12  	"math/rand"
    13  	"net"
    14  	"strconv"
    15  	"time"
    16  )
    17  
    18  func CreateSignCertToFile(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrIP string, expireDays int, name string) (err error) {
    19  	cert, key, err := CreateSignCert(rootCa, rootKey, domainOrIP, expireDays)
    20  	if err != nil {
    21  		return
    22  	}
    23  	err = ioutil.WriteFile(name+".crt", cert, 0755)
    24  	if err != nil {
    25  		return
    26  	}
    27  	err = ioutil.WriteFile(name+".key", key, 0755)
    28  	return
    29  }
    30  func CreateSignCert(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrIP string, expireDays int) (certBytes []byte, keyBytes []byte, err error) {
    31  	cer := &x509.Certificate{
    32  		SerialNumber: big.NewInt(rand.Int63()), //证书序列号
    33  		Subject: pkix.Name{
    34  			Country:            []string{getCountry()},
    35  			Organization:       []string{domainOrIP},
    36  			OrganizationalUnit: []string{domainOrIP},
    37  			CommonName:         domainOrIP,
    38  		},
    39  		NotBefore:             time.Now().Add(-time.Hour),
    40  		NotAfter:              time.Now().Add(time.Hour * 24 * time.Duration(expireDays)),
    41  		BasicConstraintsValid: true,
    42  		IsCA:        false,
    43  		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
    44  		//KeyUsage:       x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment,
    45  		EmailAddresses: []string{},
    46  		IPAddresses:    []net.IP{},
    47  	}
    48  	if ip := net.ParseIP(domainOrIP); ip != nil {
    49  		cer.IPAddresses = append(cer.IPAddresses, ip)
    50  	} else {
    51  		cer.DNSNames = append(cer.DNSNames, domainOrIP)
    52  	}
    53  
    54  	// cer.IPAddresses = append(cer.IPAddresses, alternateIPs...)
    55  	// cer.DNSNames = append(cer.DNSNames, alternateDNS...)
    56  
    57  	//生成公钥私钥对
    58  	priKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
    59  	if err != nil {
    60  		return
    61  	}
    62  	certBytes, err = x509.CreateCertificate(cryptorand.Reader, cer, rootCa, &priKey.PublicKey, rootKey)
    63  	if err != nil {
    64  		return
    65  	}
    66  
    67  	//编码证书文件和私钥文件
    68  	caPem := &pem.Block{
    69  		Type:  "CERTIFICATE",
    70  		Bytes: certBytes,
    71  	}
    72  	certBytes = pem.EncodeToMemory(caPem)
    73  
    74  	buf := x509.MarshalPKCS1PrivateKey(priKey)
    75  	keyPem := &pem.Block{
    76  		Type:  "RSA PRIVATE KEY",
    77  		Bytes: buf,
    78  	}
    79  	keyBytes = pem.EncodeToMemory(keyPem)
    80  	return
    81  }
    82  func CreateCaToFile(name, domainOrIP string, expireDays int) (err error) {
    83  	ca, key, err := CreateCa(domainOrIP, expireDays)
    84  	if err != nil {
    85  		return
    86  	}
    87  	err = ioutil.WriteFile(name+".crt", ca, 0755)
    88  	if err != nil {
    89  		return
    90  	}
    91  	err = ioutil.WriteFile(name+".key", key, 0755)
    92  	return
    93  }
    94  func CreateCa(organization string, expireDays int) (certBytes []byte, keyBytes []byte, err error) {
    95  	priv, err := rsa.GenerateKey(cryptorand.Reader, 2048)
    96  	if err != nil {
    97  		return nil, nil, err
    98  	}
    99  
   100  	template := x509.Certificate{
   101  		SerialNumber: big.NewInt(1),
   102  		Subject: pkix.Name{
   103  			CommonName:         organization,
   104  			Organization:       []string{organization},
   105  			OrganizationalUnit: []string{organization},
   106  			Country:            []string{getCountry()},
   107  		},
   108  		NotBefore: time.Now().Add(-time.Hour),
   109  		NotAfter:  time.Now().Add(time.Hour * 24 * time.Duration(expireDays)),
   110  
   111  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
   112  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
   113  		BasicConstraintsValid: true,
   114  		IsCA: true,
   115  	}
   116  
   117  	derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, &template, &priv.PublicKey, priv)
   118  	if err != nil {
   119  		return nil, nil, err
   120  	}
   121  
   122  	// Generate cert
   123  	certBuffer := bytes.Buffer{}
   124  	if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
   125  		return nil, nil, err
   126  	}
   127  
   128  	// Generate key
   129  	keyBuffer := bytes.Buffer{}
   130  	if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
   131  		return nil, nil, err
   132  	}
   133  
   134  	return certBuffer.Bytes(), keyBuffer.Bytes(), nil
   135  }
   136  func ParseCertAndKeyBytes(certPemFileByes, keyFileBytes []byte) (cert *x509.Certificate, privateKey *rsa.PrivateKey, err error) {
   137  	//解析根证书
   138  	cert, err = ParseCertBytes(certPemFileByes)
   139  	if err != nil {
   140  		return
   141  	}
   142  	//解析私钥
   143  	privateKey, err = ParseKeyBytes(keyFileBytes)
   144  	return
   145  }
   146  func ParseCertAndKey(certPemFile, keyFile string) (cert *x509.Certificate, privateKey *rsa.PrivateKey, err error) {
   147  	//解析根证书
   148  	cert, err = ParseCert(certPemFile)
   149  	if err != nil {
   150  		return
   151  	}
   152  	//解析私钥
   153  	privateKey, err = ParseKey(keyFile)
   154  	return
   155  }
   156  func ParseCert(certPemFile string) (cert *x509.Certificate, err error) {
   157  	//解析证书
   158  	certFile_, err := ioutil.ReadFile(certPemFile)
   159  	if err != nil {
   160  		return
   161  	}
   162  	cert, err = ParseCertBytes(certFile_)
   163  	return
   164  }
   165  func ParseKey(keyFile string) (key *rsa.PrivateKey, err error) {
   166  	//解析证书
   167  	keyFile_, err := ioutil.ReadFile(keyFile)
   168  	if err != nil {
   169  		return
   170  	}
   171  	key, err = ParseKeyBytes(keyFile_)
   172  	return
   173  }
   174  func ParseCertBytes(certPemFileBytes []byte) (cert *x509.Certificate, err error) {
   175  	caBlock, _ := pem.Decode(certPemFileBytes)
   176  	cert, err = x509.ParseCertificate(caBlock.Bytes)
   177  	return
   178  }
   179  func ParseKeyBytes(keyFileBytes []byte) (praKey *rsa.PrivateKey, err error) {
   180  	keyBlock, _ := pem.Decode(keyFileBytes)
   181  	praKey, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes)
   182  	return
   183  }
   184  func getCountry() string {
   185  	CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"}
   186  	return CList[int(randInt(4))%len(CList)]
   187  }
   188  func randInt(strLen int) int64 {
   189  	codes := "123456789"
   190  	codeLen := len(codes)
   191  	data := make([]byte, strLen)
   192  	rand.Seed(time.Now().UnixNano() + rand.Int63() + rand.Int63() + rand.Int63() + rand.Int63())
   193  	for i := 0; i < strLen; i++ {
   194  		idx := rand.Intn(codeLen)
   195  		data[i] = byte(codes[idx])
   196  	}
   197  	i, _ := strconv.ParseInt(string(data), 10, 64)
   198  	return i
   199  }