Golang的TLS通信,证书文件使用.

package main

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

func main() {
	info := CertInformation{Country: []string{"中国"}, Organization: []string{"游戏蜗牛"},
		OrganizationalUnit: []string{"blog.csdn.net/fyxichen"}, EmailAddress: []string{"[email protected]"},
		StreetAddress: []string{"中心大道西171"}, Province: []string{"江苏省·工业园区"}, SubjectKeyId: []byte{1, 2, 3, 4, 5, 6},
		Certificate: "client.crt", PrivateKey: "client.key", ROOTCertificate: "server.pem", ROOTPrivateKey: "server.key"}
	err := CreateCerts(info)
	if err != nil {
		println(err.Error())
	}
}

type CertInformation struct {
	Country            []string
	Organization       []string
	OrganizationalUnit []string
	EmailAddress       []string
	Province           []string
	StreetAddress      []string
	SubjectKeyId       []byte
	Certificate        string
	PrivateKey         string
	ROOTCertificate    string
	ROOTPrivateKey     string
}

func CreateCerts(info CertInformation) error {

	var rootPrivateKey *rsa.PrivateKey
	var rootcertificate *x509.Certificate
	var err error
	ca := newCertificate(info)
	priv, _ := rsa.GenerateKey(rand.Reader, 2048)

	//读取根证书
	if info.Certificate != "" && info.PrivateKey != "" {
		rootcertificate, rootPrivateKey, err = parseCerts(info.ROOTCertificate, info.ROOTPrivateKey)
		if os.IsNotExist(err) {
			rootPrivateKey, _ = rsa.GenerateKey(rand.Reader, 2048)
			rootcertificate = ca
			ca_b, err := x509.CreateCertificate(rand.Reader, rootcertificate, rootcertificate, &rootPrivateKey.PublicKey, rootPrivateKey)
			if err != nil {
				return err
			}
			err = write(info.ROOTCertificate, "CERTIFICATE", ca_b)
			if err != nil {
				return err
			}
			priv_b := x509.MarshalPKCS1PrivateKey(rootPrivateKey)
			err = write(info.ROOTPrivateKey, "PRIVATE KEY", priv_b)
			if err != nil {
				return err
			}
		} else if err != nil {
			return err
		}
	} else {
		rootcertificate = ca
		rootPrivateKey = priv
	}

	ca_b, err := x509.CreateCertificate(rand.Reader, ca, rootcertificate, &priv.PublicKey, rootPrivateKey)
	if err != nil {
		return err
	}
	err = write(info.Certificate, "CERTIFICATE", ca_b)
	if err != nil {
		return err
	}

	priv_b := x509.MarshalPKCS1PrivateKey(priv)
	err = write(info.PrivateKey, "PRIVATE KEY", priv_b)
	if err != nil {
		return err
	}

	return nil
}

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

func parseCerts(ROOTCertificate, ROOTPrivateKey string) (*x509.Certificate, *rsa.PrivateKey, error) {
	var rootPrivateKey *rsa.PrivateKey
	var rootcertificate *x509.Certificate

	buf, err := ioutil.ReadFile(ROOTCertificate)
	if err != nil {
		return nil, nil, err
	}
	p := &pem.Block{}
	p, buf = pem.Decode(buf)
	rootcertificate, err = x509.ParseCertificate(p.Bytes)
	if err != nil {
		return nil, nil, err
	}
	buf, err = ioutil.ReadFile(ROOTPrivateKey)
	if err != nil {
		return nil, nil, err
	}
	p, buf = pem.Decode(buf)
	rootPrivateKey, err = x509.ParsePKCS1PrivateKey(p.Bytes)
	if err != nil {
		return nil, nil, err
	}
	return rootcertificate, rootPrivateKey, nil
}

func newCertificate(info CertInformation) *x509.Certificate {
	return &x509.Certificate{
		SerialNumber: big.NewInt(1653),
		Subject: pkix.Name{
			Country:            info.Country,
			Organization:       info.Organization,
			OrganizationalUnit: info.OrganizationalUnit,
			Province:           info.Province,
			StreetAddress:      info.StreetAddress,
		},
		NotBefore:             time.Now(),
		NotAfter:              time.Now().AddDate(10, 0, 0),
		SubjectKeyId:          info.SubjectKeyId,
		BasicConstraintsValid: true,
		IsCA:           true,
		ExtKeyUsage:    []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
		KeyUsage:       x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
		EmailAddresses: info.EmailAddress,
	}
}

你可能感兴趣的:(Golang)