// RAINBOND, Application Management Platform // Copyright (C) 2014-2017 Goodrain Co., Ltd. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. For any non-GPL usage of Rainbond, // one or multiple Commercial Licenses authorized by Goodrain Co., Ltd. // must be obtained first. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see . package main import ( "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "io/ioutil" "math/big" rd "math/rand" "net" "os" "time" ) func init() { rd.Seed(time.Now().UnixNano()) } type CertInformation struct { Country []string Organization []string OrganizationalUnit []string EmailAddress []string Province []string Locality []string CommonName string CrtName, KeyName string IsCA bool Names []pkix.AttributeTypeAndValue IPAddresses []net.IP Domains []string } //CreateCRT create crt func CreateCRT(RootCa *x509.Certificate, RootKey *rsa.PrivateKey, info CertInformation) error { Crt := newCertificate(info) Key, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err } var buf []byte if RootCa == nil || RootKey == nil { //create ca cert buf, err = x509.CreateCertificate(rand.Reader, Crt, Crt, &Key.PublicKey, Key) if err != nil { return err } keybuf := x509.MarshalPKCS1PrivateKey(Key) err = write(info.KeyName, "PRIVATE KEY", keybuf) } else { //create cert by ca buf, err = x509.CreateCertificate(rand.Reader, Crt, RootCa, &Key.PublicKey, RootKey) if err != nil { return err } keybuf := x509.MarshalPKCS1PrivateKey(Key) err = write(info.KeyName, "RSA PRIVATE KEY", keybuf) } if err != nil { return err } err = write(info.CrtName, "CERTIFICATE", buf) 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{Bytes: p, Type: Type} return pem.Encode(File, b) } //Parse Parse func Parse(crtPath, keyPath string) (rootcertificate *x509.Certificate, rootPrivateKey *rsa.PrivateKey, err error) { rootcertificate, err = ParseCrt(crtPath) if err != nil { return } rootPrivateKey, err = ParseKey(keyPath) return } //ParseCrt ParseCrt 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) } //ParseKey ParseKey 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 newCertificate(info CertInformation) *x509.Certificate { return &x509.Certificate{ SerialNumber: big.NewInt(rd.Int63()), Subject: pkix.Name{ Country: info.Country, Organization: info.Organization, OrganizationalUnit: info.OrganizationalUnit, Province: info.Province, CommonName: info.CommonName, Locality: info.Locality, ExtraNames: info.Names, }, NotBefore: time.Now(), //start time NotAfter: time.Now().AddDate(20, 0, 0), //end time BasicConstraintsValid: true, //basic IsCA: info.IsCA, //是否是根证书 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, //证书用途 KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, EmailAddresses: info.EmailAddress, IPAddresses: info.IPAddresses, DNSNames: info.Domains, } }