package rsas
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"io"
"io/IoUtil"
"math/big"
rd "math/rand"
"net"
"os"
"path/filepath"
"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
DNSNames []string
IPAddresses []net.IP
IsCA bool
Names []pkix.AttributeTypeAndValue
CrtName,KeyName string
EncryptLen int
DateLen int
}
func SignerCRT(rootcrt *x509.Certificate,rootkey *rsa.PrivateKey,crt *x509.Certificate) ([]byte,error) {
if rootcrt == nil || rootkey == nil {
return nil,errors.New("Root crt is null")
}
buf,err := x509.CreateCertificate(rand.Reader,crt,rootcrt,crt.PublicKey,rootkey)
b := bytes.NewBuffer(nil)
err = Write(b,buf,"CERTIFICATE")
return b.Bytes(),err
}
func CheckSignature(rootcrt *x509.Certificate,crt []byte) error {
ca,err := ParseCrt(crt)
if err != nil {
return err
}
return ca.CheckSignatureFrom(rootcrt)
}
func CreatePemCRT(info CertInformation) (pemcrt []byte,pemkey []byte,err error) {
pemcrt,pemkey,err = CreateCRT(nil,nil,info)
if err != nil {
return
}
cFile := bytes.NewBuffer([]byte{})
err = Write(cFile,pemcrt,"CERTIFICATE")
if err != nil {
return
}
pemcrt = cFile.Bytes()
kFile := bytes.NewBuffer([]byte{})
err = Write(kFile,"PRIVATE KEY")
pemkey = kFile.Bytes()
return
}
func CreateCRT(RootCa *x509.Certificate,RootKey *rsa.PrivateKey,info CertInformation) (crt []byte,key []byte,err error) {
Crt := newCertificate(info)
if info.EncryptLen < 512 {
info.EncryptLen = 512
}
Key,err := rsa.GenerateKey(rand.Reader,info.EncryptLen)
if err != nil {
return
}
key = x509.MarshalPKCS1PrivateKey(Key)
if RootCa == nil || RootKey == nil {
crt,err = x509.CreateCertificate(rand.Reader,Crt,&Key.PublicKey,Key)
} else {
crt,RootCa,RootKey)
}
return
}
func WirteFile(path string,buf []byte,typ string) error {
os.MkdirAll(filepath.Dir(path), 0666)
File,err := os.Create(path)
defer File.Close()
if err != nil {
return err
}
return Write(File,typ)
}
func Write(w io.Writer,typ string) error {
b := &pem.Block{Bytes: buf,Type: typ}
return pem.Encode(w,b)
}
func Parse(crtPath,keyPath string) (rootcertificate *x509.Certificate,rootPrivateKey *rsa.PrivateKey,err error) {
buf,err := IoUtil.ReadFile(crtPath)
if err != nil {
return
}
rootcertificate,err = ParseCrt(buf)
if err != nil {
return
}
buf,err = IoUtil.ReadFile(keyPath)
if err != nil {
return
}
rootPrivateKey,err = ParseKey(buf)
return
}
func ParseCrt(buf []byte) (*x509.Certificate,error) {
p := &pem.Block{}
p,_ = pem.Decode(buf)
return x509.ParseCertificate(p.Bytes)
}
func ParseKey(buf []byte) (*rsa.PrivateKey,error) {
p,buf := pem.Decode(buf)
return x509.ParsePKCS1PrivateKey(p.Bytes)
}
func newCertificate(info CertInformation) *x509.Certificate {
if info.DateLen == 0 {
info.DateLen = 10
}
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(),NotAfter: time.Now().AddDate(info.DateLen, 0, 0),BasicConstraintsValid: true,DNSNames: info.DNSNames,IPAddresses: info.IPAddresses,IsCA: info.IsCA,ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth,x509.ExtKeyUsageServerAuth},KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,EmailAddresses: info.EmailAddress,}
}