2018-08-02 12:16:50 +08:00
|
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
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
|
2018-08-02 22:53:37 +08:00
|
|
|
Domains []string
|
2018-08-02 12:16:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//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 {
|
2018-08-02 22:53:37 +08:00
|
|
|
//create ca cert
|
2018-08-02 12:16:50 +08:00
|
|
|
buf, err = x509.CreateCertificate(rand.Reader, Crt, Crt, &Key.PublicKey, Key)
|
2018-08-14 16:44:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
keybuf := x509.MarshalPKCS1PrivateKey(Key)
|
|
|
|
err = write(info.KeyName, "PRIVATE KEY", keybuf)
|
2018-08-02 12:16:50 +08:00
|
|
|
} else {
|
2018-08-02 22:53:37 +08:00
|
|
|
//create cert by ca
|
2018-08-02 12:16:50 +08:00
|
|
|
buf, err = x509.CreateCertificate(rand.Reader, Crt, RootCa, &Key.PublicKey, RootKey)
|
2018-08-14 16:44:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
keybuf := x509.MarshalPKCS1PrivateKey(Key)
|
|
|
|
err = write(info.KeyName, "RSA PRIVATE KEY", keybuf)
|
2018-08-02 12:16:50 +08:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = write(info.CrtName, "CERTIFICATE", buf)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-14 16:44:57 +08:00
|
|
|
return nil
|
2018-08-02 12:16:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//编码写入文件
|
|
|
|
func write(filename, Type string, p []byte) error {
|
|
|
|
File, err := os.Create(filename)
|
|
|
|
defer File.Close()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-02 22:53:37 +08:00
|
|
|
var b = &pem.Block{Bytes: p, Type: Type}
|
2018-08-02 12:16:50 +08:00
|
|
|
return pem.Encode(File, b)
|
|
|
|
}
|
|
|
|
|
2018-08-02 22:53:37 +08:00
|
|
|
//Parse Parse
|
2018-08-02 12:16:50 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2018-08-02 22:53:37 +08:00
|
|
|
//ParseCrt ParseCrt
|
2018-08-02 12:16:50 +08:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-08-02 22:53:37 +08:00
|
|
|
//ParseKey ParseKey
|
2018-08-02 12:16:50 +08:00
|
|
|
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,
|
|
|
|
},
|
2018-08-02 22:53:37 +08:00
|
|
|
NotBefore: time.Now(), //start time
|
|
|
|
NotAfter: time.Now().AddDate(20, 0, 0), //end time
|
|
|
|
BasicConstraintsValid: true, //basic
|
2018-08-02 12:16:50 +08:00
|
|
|
IsCA: info.IsCA, //是否是根证书
|
|
|
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, //证书用途
|
|
|
|
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
|
|
|
EmailAddresses: info.EmailAddress,
|
|
|
|
IPAddresses: info.IPAddresses,
|
2018-08-02 22:53:37 +08:00
|
|
|
DNSNames: info.Domains,
|
2018-08-02 12:16:50 +08:00
|
|
|
}
|
|
|
|
}
|