Skip to content

Commit

Permalink
ca certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
AbericYang committed Sep 23, 2019
1 parent 7ee9c12 commit 3cc7be6
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 56 deletions.
75 changes: 56 additions & 19 deletions ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"math/big"
rd "math/rand"
"net"
"net/url"
"os"
"time"
)
Expand Down Expand Up @@ -100,11 +103,20 @@ func (ca *CACommon) GenerateRSACertificateRequestFPWithPass(cert *CertRequestFP,
return ca.GenerateCertificateRequest(certModel)
}

// GenerateECCCertificateRequestFP 生成证书签名请求文件
// GenerateECCCertificateRequest 生成证书签名请求文件
//
// cert 证书生成请求对象
func (ca *CACommon) GenerateECCCertificateRequestFP(cert *CertRequestFP) (csr []byte, err error) {
priECCKey, err := CryptoECC().LoadPriPem(cert.PrivateKeyFilePath)
func (ca *CACommon) GenerateECCCertificateRequest(cert *CertRequest) (csr []byte, err error) {
return ca.GenerateECCCertificateRequestWithPass(cert, "")
}

// GenerateECCCertificateRequestWithPass 生成证书签名请求文件
//
// cert 证书生成请求对象
//
// password 生成时输入的密码
func (ca *CACommon) GenerateECCCertificateRequestWithPass(cert *CertRequest, password string) (csr []byte, err error) {
priECCKey, err := CryptoECC().LoadPriPemWithPass(cert.PrivateKeyData, password)
if err != nil {
return nil, err
}
Expand All @@ -113,13 +125,20 @@ func (ca *CACommon) GenerateECCCertificateRequestFP(cert *CertRequestFP) (csr []
return ca.GenerateCertificateRequest(certModel)
}

// GenerateECCCertificateRequestFP 生成证书签名请求文件
//
// cert 证书生成请求对象
func (ca *CACommon) GenerateECCCertificateRequestFP(cert *CertRequestFP) (csr []byte, err error) {
return ca.GenerateECCCertificateRequestFPWithPass(cert, "")
}

// GenerateECCCertificateRequestFPWithPass 生成证书签名请求文件
//
// cert 证书生成请求对象
//
// password 生成时输入的密码
func (ca *CACommon) GenerateECCCertificateRequestFPWithPass(cert *CertRequestFP, password string) (csr []byte, err error) {
priECCKey, err := CryptoECC().LoadPriPemWithPass(cert.PrivateKeyFilePath, password)
priECCKey, err := CryptoECC().LoadPriPemFPWithPass(cert.PrivateKeyFilePath, password)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -151,19 +170,16 @@ func (ca *CACommon) GenerateCertificateRequest(cert *CertRequestModel) (csr []by
//
// cert 签名数字证书对象
func (ca *CACommon) GenerateCertificate(cert *Cert) (certData []byte, err error) {
bigInt, err := rand.Int(rand.Reader, big.NewInt(time.Now().Unix()))
if nil != err {
return nil, err
}
template := &x509.Certificate{
SerialNumber: bigInt,
SerialNumber: big.NewInt(rd.Int63()), // 证书序列号
Subject: cert.Subject,
NotBefore: time.Now().Add(cert.NotBeforeDays * 24 * time.Hour),
NotAfter: time.Now().Add(cert.NotAfterDays * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
SignatureAlgorithm: x509.SHA1WithRSA, // 签名算法选择SHA1WithRSA
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
NotBefore: cert.NotBeforeDays,
NotAfter: cert.NotAfterDays,
BasicConstraintsValid: cert.BasicConstraintsValid,
IsCA: cert.IsCA,
SignatureAlgorithm: cert.SignatureAlgorithm,
ExtKeyUsage: cert.ExtKeyUsage,
KeyUsage: cert.KeyUsage,
SubjectKeyId: []byte{1, 2, 3},
}
certData, err = x509.CreateCertificate(rand.Reader, template, template, cert.PublicKey, cert.PrivateKey)
Expand Down Expand Up @@ -191,10 +207,15 @@ func (ca *CACommon) GenerateCertificate(cert *Cert) (certData []byte, err error)

// Cert 签名数字证书对象
type Cert struct {
CertificateFilePath string // 签名后数字证书文件存储路径
Subject pkix.Name // Subject 签名信息
PrivateKey, PublicKey interface{} // 公私钥
NotBeforeDays, NotAfterDays time.Duration // 在指定时间之后生效及之前失效
CertificateFilePath string // 签名后数字证书文件存储路径
Subject pkix.Name // Subject 签名信息
PrivateKey, PublicKey interface{} // 公私钥
BasicConstraintsValid bool // 基本的有效性约束
IsCA bool // 是否是根证书
NotBeforeDays, NotAfterDays time.Time // 在指定时间之后生效及之前失效
ExtKeyUsage []x509.ExtKeyUsage // ExtKeyUsage表示对给定键有效的扩展操作集。每个ExtKeyUsage*常量定义一个惟一的操作。
KeyUsage x509.KeyUsage // KeyUsage表示对给定密钥有效的操作集。它是KeyUsage*常量的位图。
SignatureAlgorithm x509.SignatureAlgorithm // signatureAlgorithm 生成证书时候采用的签名算法
}

// CertRequest 证书生成请求对象
Expand All @@ -203,12 +224,20 @@ type CertRequest struct {
CertificateRequestFilePath string // certificateFilePath 指定生成的证书签名请求文件路径,如'/etc/rootCA.csr'
SignatureAlgorithm x509.SignatureAlgorithm // signatureAlgorithm 生成证书时候采用的签名算法
Subject pkix.Name // Subject 签名信息
DNSNames []string // DNSNames DNS限制
EmailAddresses []string // EmailAddresses 邮箱地址限制
IPAddresses []net.IP // IPAddresses IP地址限制
URIs []*url.URL // URIs URL地址限制
}

func (cert *CertRequest) init() *CertRequestModel {
temp := &x509.CertificateRequest{
SignatureAlgorithm: cert.SignatureAlgorithm,
Subject: cert.Subject,
DNSNames: cert.DNSNames,
EmailAddresses: cert.EmailAddresses,
IPAddresses: cert.IPAddresses,
URIs: cert.URIs,
}
return &CertRequestModel{
CertificateRequestFilePath: cert.CertificateRequestFilePath,
Expand All @@ -222,12 +251,20 @@ type CertRequestFP struct {
CertificateRequestFilePath string // certificateFilePath 指定生成的证书签名请求文件路径,如'/etc/rootCA.csr'
SignatureAlgorithm x509.SignatureAlgorithm // signatureAlgorithm 生成证书时候采用的签名算法
Subject pkix.Name // Subject 签名信息
DNSNames []string // DNSNames DNS限制
EmailAddresses []string // EmailAddresses 邮箱地址限制
IPAddresses []net.IP // IPAddresses IP地址限制
URIs []*url.URL // URIs URL地址限制
}

func (cert *CertRequestFP) init() *CertRequestModel {
temp := &x509.CertificateRequest{
SignatureAlgorithm: cert.SignatureAlgorithm,
Subject: cert.Subject,
DNSNames: cert.DNSNames,
EmailAddresses: cert.EmailAddresses,
IPAddresses: cert.IPAddresses,
URIs: cert.URIs,
}
return &CertRequestModel{
CertificateRequestFilePath: cert.CertificateRequestFilePath,
Expand Down
121 changes: 109 additions & 12 deletions ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"io/ioutil"
"net"
"path/filepath"
"testing"
"time"
)

var (
Expand All @@ -44,7 +46,7 @@ var (

caPriKeyFileName = "rootCA.key" // ca 私钥
caCertificateRequestFileName = "rootCA.csr" // 证书签名请求文件
//caCertificateFileName = "rootCA.crt"
caCertificateFileName = "rootCA.crt"

errCA error
)
Expand Down Expand Up @@ -119,17 +121,34 @@ func TestCACommon_GenerateRSAPKCS1PrivateKeyFP(t *testing.T) {
}

func TestCACommon_GenerateRSAPKCS8PrivateKeyFP(t *testing.T) {
if _, errCA = CryptoRSA().GeneratePKCS8PriKey(1024, pathcarsapksc81024, caPriKeyFileName); nil != errCA {
if priRSAKey, errCA = CryptoRSA().GeneratePKCS8PriKey(1024, pathcarsapksc81024, caPriKeyFileName); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateRSACertificateRequestFP(&CertRequestFP{
PrivateKeyFilePath: filepath.Join(pathcarsapksc81024, caPriKeyFileName),
CertificateRequestFilePath: filepath.Join(pathcarsapksc81024, caCertificateRequestFileName),
SignatureAlgorithm: x509.SHA384WithRSAPSS,
Subject: CAMockSubject,
EmailAddresses: []string{"test@test.com"},
IPAddresses: []net.IP{net.ParseIP("192.168.1.59")},
}, CryptoRSA().PKSC8()); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateCertificate(&Cert{
CertificateFilePath: filepath.Join(pathcarsapksc81024, caCertificateFileName),
Subject: CAMockSubject,
PrivateKey: priRSAKey,
PublicKey: priRSAKey.Public(),
NotAfterDays: time.Now(),
NotBeforeDays: time.Now().Add(5000 * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, //证书用途(客户端认证,数据加密)
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
SignatureAlgorithm: x509.SHA384WithRSAPSS,
}); nil != errCA {
t.Error(errCA)
}

if _, errCA = CryptoRSA().GeneratePKCS8PriKeyWithPass(2048, pathcarsapksc82048, caPriKeyFileName, "123456"); nil != errCA {
t.Error(errCA)
Expand All @@ -148,20 +167,38 @@ func TestCACommon_GenerateECCPrivateKey(t *testing.T) {
if errCA = CryptoECC().GeneratePemPriKey(pathcaeccpemp224, caPriKeyFileName, elliptic.P224()); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateECCCertificateRequestFP(&CertRequestFP{
PrivateKeyFilePath: filepath.Join(pathcaeccpemp224, caPriKeyFileName),
priData, errECC = ioutil.ReadFile(filepath.Join(pathcaeccpemp224, caPriKeyFileName))
if nil != errECC {
t.Error(errECC)
}
if _, errCA = CA().GenerateECCCertificateRequest(&CertRequest{
PrivateKeyData: priData,
CertificateRequestFilePath: filepath.Join(pathcaeccpemp224, caCertificateRequestFileName),
SignatureAlgorithm: x509.ECDSAWithSHA256,
Subject: CAMockSubject,
EmailAddresses: []string{"test@test.com"},
IPAddresses: []net.IP{net.ParseIP("192.168.1.59")},
}); nil != errCA {
t.Error(errCA)
}
if priKeyP224, errCA = CryptoECC().LoadPriPem(priData); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateCertificate(&Cert{
CertificateFilePath: filepath.Join(pathcaeccpemp224, caCertificateFileName),
Subject: CAMockSubject,
PrivateKey: priKeyP224,
PublicKey: priKeyP224.Public(),
NotAfterDays: time.Now(),
NotBeforeDays: time.Now().Add(5000 * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
SignatureAlgorithm: x509.ECDSAWithSHA256,
}); nil != errCA {
t.Error(errCA)
}
//if _, errCA = CA().GenerateCertificate(&Cert{
// CertificateFilePath:filepath.Join(pathcaeccpemp224, caCertificateFileName),
// Subject:CAMockSubject,
//});nil!=errCA {
// t.Error(errCA)
//}

if errCA = CryptoECC().GeneratePemPriKey(pathcaeccpemp256, caPriKeyFileName, elliptic.P256()); nil != errCA {
t.Error(errCA)
Expand All @@ -171,21 +208,63 @@ func TestCACommon_GenerateECCPrivateKey(t *testing.T) {
CertificateRequestFilePath: filepath.Join(pathcaeccpemp256, caCertificateRequestFileName),
SignatureAlgorithm: x509.ECDSAWithSHA256,
Subject: CAMockSubject,
EmailAddresses: []string{"test@test.com"},
IPAddresses: []net.IP{net.ParseIP("192.168.1.59")},
}); nil != errCA {
t.Error(errCA)
}
if priKeyP256, errCA = CryptoECC().LoadPriPemFP(filepath.Join(pathcaeccpemp256, caPriKeyFileName)); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateCertificate(&Cert{
CertificateFilePath: filepath.Join(pathcaeccpemp256, caCertificateFileName),
Subject: CAMockSubject,
PrivateKey: priKeyP256,
PublicKey: priKeyP256.Public(),
NotAfterDays: time.Now(),
NotBeforeDays: time.Now().Add(5000 * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
SignatureAlgorithm: x509.ECDSAWithSHA256,
}); nil != errCA {
t.Error(errCA)
}

if errCA = CryptoECC().GeneratePemPriKeyWithPass(pathcaeccpemp384, caPriKeyFileName, "123456", elliptic.P384()); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateECCCertificateRequestFPWithPass(&CertRequestFP{
PrivateKeyFilePath: filepath.Join(pathcaeccpemp384, caPriKeyFileName),
priData, errECC = ioutil.ReadFile(filepath.Join(pathcaeccpemp384, caPriKeyFileName))
if nil != errECC {
t.Error(errECC)
}
if _, errCA = CA().GenerateECCCertificateRequestWithPass(&CertRequest{
PrivateKeyData: priData,
CertificateRequestFilePath: filepath.Join(pathcaeccpemp384, caCertificateRequestFileName),
SignatureAlgorithm: x509.ECDSAWithSHA384,
Subject: CAMockSubject,
}, "123456"); nil != errCA {
t.Error(errCA)
}
if priKeyP384, errCA = CryptoECC().LoadPriPemFPWithPass(filepath.Join(pathcaeccpemp384, caPriKeyFileName), "123456"); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateCertificate(&Cert{
CertificateFilePath: filepath.Join(pathcaeccpemp384, caCertificateFileName),
Subject: CAMockSubject,
PrivateKey: priKeyP384,
PublicKey: priKeyP384.Public(),
NotAfterDays: time.Now(),
NotBeforeDays: time.Now().Add(5000 * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
SignatureAlgorithm: x509.ECDSAWithSHA384,
}); nil != errCA {
t.Error(errCA)
}

if errCA = CryptoECC().GeneratePemPriKeyWithPass(pathcaeccpemp521, caPriKeyFileName, "123456", elliptic.P521()); nil != errCA {
t.Error(errCA)
Expand All @@ -198,4 +277,22 @@ func TestCACommon_GenerateECCPrivateKey(t *testing.T) {
}, "123456"); nil != errCA {
t.Error(errCA)
}
if priKeyP521, errCA = CryptoECC().LoadPriPemFPWithPass(filepath.Join(pathcaeccpemp521, caPriKeyFileName), "123456"); nil != errCA {
t.Error(errCA)
}
if _, errCA = CA().GenerateCertificate(&Cert{
CertificateFilePath: filepath.Join(pathcaeccpemp521, caCertificateFileName),
Subject: CAMockSubject,
PrivateKey: priKeyP521,
PublicKey: priKeyP521.Public(),
NotAfterDays: time.Now(),
NotBeforeDays: time.Now().Add(5000 * 24 * time.Hour),
BasicConstraintsValid: true,
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageCRLSign | x509.KeyUsageDataEncipherment,
SignatureAlgorithm: x509.ECDSAWithSHA512,
}); nil != errCA {
t.Error(errCA)
}
}
46 changes: 41 additions & 5 deletions ecc.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,19 +293,55 @@ func (e *ECCCommon) SavePriPemWithPass(privateKey *ecdsa.PrivateKey, passwd, fil
return nil
}

// LoadPriPem 从文件中加载私钥
// LoadPriPem 解析私钥
//
// privateKey 私钥内容,如取出字符串'priData',则传入'string(priData)'即可
func (e *ECCCommon) LoadPriPem(privateKey []byte) (*ecdsa.PrivateKey, error) {
return e.LoadPriPemWithPass(privateKey, "")
}

// LoadPriPemWithPass 解析私钥
//
// privateKey 私钥内容,如取出字符串'priData',则传入'string(priData)'即可
//
// passwd 生成privateKey时输入密码
func (e *ECCCommon) LoadPriPemWithPass(privateKey []byte, passwd string) (*ecdsa.PrivateKey, error) {
var (
pemData []byte
err error
)
if String().IsEmpty(passwd) {
pemData, err = e.pemParse(privateKey, privateECCKeyPemType)
if err != nil {
return nil, err
}
} else {
block, _ := pem.Decode(privateKey)
pemData, err = x509.DecryptPEMBlock(block, []byte(passwd))
if err != nil {
return nil, err
}
}
pri, err := x509.ParseECPrivateKey(pemData)
if nil != err {
return nil, err
}
return pri, nil
}

// LoadPriPemFP 从文件中加载私钥
//
// file 文件路径
func (e *ECCCommon) LoadPriPem(file string) (*ecdsa.PrivateKey, error) {
return e.LoadPriPemWithPass(file, "")
func (e *ECCCommon) LoadPriPemFP(file string) (*ecdsa.PrivateKey, error) {
return e.LoadPriPemFPWithPass(file, "")
}

// LoadPriPemWithPass 从文件中加载私钥
// LoadPriPemFPWithPass 从文件中加载私钥
//
// file 文件路径
//
// passwd 生成privateKey时输入密码
func (e *ECCCommon) LoadPriPemWithPass(file, passwd string) (*ecdsa.PrivateKey, error) {
func (e *ECCCommon) LoadPriPemFPWithPass(file, passwd string) (*ecdsa.PrivateKey, error) {
var (
pemData []byte
err error
Expand Down
Loading

0 comments on commit 3cc7be6

Please sign in to comment.