侧边栏壁纸
  • 累计撰写 71 篇文章
  • 累计创建 87 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

Golang生成x509证书

KunkkaWu
2021-10-14 / 0 评论 / 2 点赞 / 12,975 阅读 / 580 字 / 正在检测是否收录...
package util

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"crypto/x509/pkix"
	"encoding/pem"
	"io/ioutil"
	"math/big"
	"net"
	"os"
	"time"
)

type CertTemplate struct {
	Country            []string
	Organization       []string
	OrganizationalUnit []string
	EmailAddress       []string
	Province           []string
	Locality           []string
	PrivateKey         *rsa.PrivateKey
	CommonName         string
	CrtName, KeyName   string
	IsCA               bool
	Names              []pkix.AttributeTypeAndValue
	DNSNames           []string
	IPAddresses        []net.IP
}

func CreateCRT(RootCa *x509.Certificate, RootKey *rsa.PrivateKey, info CertTemplate) error {
	Crt := newCertificate(info)

	var buf []byte
	buf, err := x509.CreateCertificate(rand.Reader, Crt, RootCa, &info.PrivateKey.PublicKey, RootKey)
	if err != nil {
		return err
	}

	err = writeToFile(info.CrtName, "CERTIFICATE", buf)
	if err != nil {
		return err
	}

	buf = x509.MarshalPKCS1PrivateKey(info.PrivateKey)
	return writeToFile(info.KeyName, "PRIVATE KEY", buf)
}

func newCertificate(info CertTemplate) *x509.Certificate {
	sn, _ := rand.Int(rand.Reader, big.NewInt(1000000))
	keyUsage := []x509.ExtKeyUsage{
		x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageCodeSigning}
	return &x509.Certificate{
		SerialNumber: sn,
		Subject: pkix.Name{
			Country:            info.Country,
			Organization:       info.Organization,
			OrganizationalUnit: info.OrganizationalUnit,
			Province:           info.Province,
			CommonName:         info.CommonName,
			Locality:           info.Locality,
			ExtraNames:         info.Names,
		},
		DNSNames:              info.DNSNames,
		IPAddresses:           info.IPAddresses,
		NotBefore:             time.Now(),                                             //证书的开始时间
		NotAfter:              time.Now().AddDate(10, 0, 0),                           //证书的结束时间
		BasicConstraintsValid: true,                                                   //基本的有效性约束
		IsCA:                  info.IsCA,                                              //是否是根证书
		ExtKeyUsage:           keyUsage,                                               //证书用途
		KeyUsage:              x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		EmailAddresses:        info.EmailAddress,
	}
}

func ParsePem(crtPath, keyPath string) (rootcertificate *x509.Certificate, rootPrivateKey *rsa.PrivateKey, err error) {
	rootcertificate, err = ParseCrt(crtPath)
	if err != nil {
		return
	}
	rootPrivateKey, err = ParseKey(keyPath)
	return
}

func ParseCrt(path string) (*x509.Certificate, error) {
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	p := &pem.Block{}
	p, buf = pem.Decode(buf)
	return x509.ParseCertificate(p.Bytes)
}

func ParseKey(path string) (*rsa.PrivateKey, error) {
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	p, buf := pem.Decode(buf)
	return x509.ParsePKCS1PrivateKey(p.Bytes)
}

func writeToFile(filename, Type string, p []byte) error {
	File, err := os.Create(filename)
	defer File.Close()
	if err != nil {
		return err
	}
	var b = &pem.Block{Bytes: p, Type: Type}
	return pem.Encode(File, b)
}


调用:

    //生成私钥
	key, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		return "", "", err
	}
	var DnsNames []string
	DnsNames = append(DnsNames, "blog.getcoder.cn")
	certTemp := util.CertTemplate{
		Country:            []string{"CN"},
		Organization:       []string{"名称"},
		OrganizationalUnit: []string{"名称"},
		EmailAddress:       nil,
		Province:           []string{"Beijing"},
		Locality:           []string{"Beijing"},
		CommonName:         "名称",
		PrivateKey:         key,
		CrtName:            crtFilePath,   //生成的证书路径 /var/cert/abc.crt
		KeyName:            keyFilePath,   //生成的私钥路径 /var/cert/abc.key
		IsCA:               false,
		DNSNames:           DnsNames,
		Names:              []pkix.AttributeTypeAndValue{{asn1.ObjectIdentifier{2, 1, 3}, "MAC_ADDR"}},
	}
	//通过CA证书路径,解析CA的证书和私钥
	caCrt, caPrivateKey, err := util.ParsePem(caCrtFilePath, caKeyFilePath)
	//通过CA证书和私钥,签发新证书
	err = util.CreateCRT(caCrt, caPrivateKey, certTemp)
	if err != nil {
		fmt.Println("Err:", err)
		return "", "", err
	}
	crtPem, err := ioutil.ReadFile(crtFilePath)
	if err != nil {
		return "", "", err
	}
	keyPem, err := ioutil.ReadFile(keyFilePath)
	if err != nil {
		return "", "", err
	}

	return string(keyPem), string(crtPem), err

2

评论区