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
评论区