mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-09 16:21:10 +08:00
【新增】私有ca
This commit is contained in:
141
backend/internal/private_ca/leaf.go
Normal file
141
backend/internal/private_ca/leaf.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package private_ca
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/tjfoc/gmsm/sm2"
|
||||
gmx509 "github.com/tjfoc/gmsm/x509"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GenerateLeafCertificate 生成叶子证书(服务器/客户端证书/邮件证书)
|
||||
func GenerateLeafCertificate(commonName string, san SAN, issuer *Certificate, keyType KeyType, usage int, keyBits int, validDays int) (*LeafCertConfig, error) {
|
||||
if issuer == nil {
|
||||
return nil, errors.New("issuer is nil")
|
||||
}
|
||||
if issuer.KeyType != keyType {
|
||||
return nil, errors.New("issuer key type mismatch")
|
||||
}
|
||||
|
||||
if keyType == KeySM2 {
|
||||
if issuer.SignGmCert == nil {
|
||||
return nil, errors.New("issuer must be a valid SM2 dual-certificate CA")
|
||||
}
|
||||
// 国密SM2证书 - 生成签名和加密双证书, 使用不同私钥
|
||||
|
||||
// 1. 为签名和加密证书分别生成私钥
|
||||
signPriv, err := generatePrivateKey(keyType, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate SM2 signing key: %w", err)
|
||||
}
|
||||
encryptPriv, err := generatePrivateKey(keyType, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate SM2 encryption key: %w", err)
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
expire := now.AddDate(0, 0, validDays)
|
||||
if validDays <= 0 {
|
||||
expire = now.AddDate(1, 0, 0)
|
||||
}
|
||||
|
||||
// 2. 创建签名证书模板
|
||||
signTmpl := &gmx509.Certificate{
|
||||
SerialNumber: big.NewInt(now.UnixNano()),
|
||||
Subject: pkix.Name{CommonName: commonName},
|
||||
NotBefore: now,
|
||||
NotAfter: expire,
|
||||
IsCA: false,
|
||||
KeyUsage: gmx509.KeyUsageDigitalSignature, // 仅用于签名
|
||||
ExtKeyUsage: []gmx509.ExtKeyUsage{gmx509.ExtKeyUsage(usage)},
|
||||
DNSNames: san.DNSNames,
|
||||
IPAddresses: san.IPAddresses,
|
||||
EmailAddresses: san.EmailAddresses,
|
||||
}
|
||||
|
||||
// 3. 创建加密证书模板
|
||||
encryptTmpl := &gmx509.Certificate{
|
||||
SerialNumber: big.NewInt(now.UnixNano() + 1), // 使用不同的序列号
|
||||
Subject: pkix.Name{CommonName: commonName},
|
||||
NotBefore: now,
|
||||
NotAfter: expire,
|
||||
IsCA: false,
|
||||
KeyUsage: gmx509.KeyUsageKeyEncipherment, // 仅用于加密
|
||||
ExtKeyUsage: []gmx509.ExtKeyUsage{gmx509.ExtKeyUsage(usage)},
|
||||
DNSNames: san.DNSNames,
|
||||
IPAddresses: san.IPAddresses,
|
||||
EmailAddresses: san.EmailAddresses,
|
||||
}
|
||||
|
||||
// 4. 使用颁发者密钥签发签名证书
|
||||
signCert, err := signSM2Cert(signTmpl, issuer.SignGmCert, signPriv.(*sm2.PrivateKey), issuer.Key.(*sm2.PrivateKey))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to sign SM2 signing cert: %w", err)
|
||||
}
|
||||
|
||||
// 5. 使用颁发者密钥签发加密证书
|
||||
encryptCert, err := signSM2Cert(encryptTmpl, issuer.EncryptGmCert, encryptPriv.(*sm2.PrivateKey), issuer.Key.(*sm2.PrivateKey))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to sign SM2 encryption cert: %w", err)
|
||||
}
|
||||
|
||||
// 6. 组装返回结果
|
||||
return &LeafCertConfig{
|
||||
CN: commonName,
|
||||
Usage: int64(usage),
|
||||
Cert: string(signCert.CertPEM),
|
||||
Key: string(signCert.KeyPEM),
|
||||
EnCert: string(encryptCert.CertPEM),
|
||||
EnKey: string(encryptCert.KeyPEM),
|
||||
Algorithm: "sm2",
|
||||
KeyLength: 256,
|
||||
NotAfter: expire.Format("2006-01-02 15:04:05"),
|
||||
NotBefore: now.Format("2006-01-02 15:04:05"),
|
||||
CreateTime: now.Format("2006-01-02 15:04:05"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 标准算法证书
|
||||
priv, err := generatePrivateKey(keyType, keyBits)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
expire := now.AddDate(0, 0, validDays)
|
||||
if validDays <= 0 {
|
||||
expire = now.AddDate(1, 0, 0)
|
||||
}
|
||||
|
||||
tmpl := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(now.UnixNano()),
|
||||
Subject: pkix.Name{CommonName: commonName},
|
||||
NotBefore: now,
|
||||
NotAfter: expire,
|
||||
IsCA: false,
|
||||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsage(usage)},
|
||||
}
|
||||
|
||||
tmpl.DNSNames = san.DNSNames
|
||||
tmpl.IPAddresses = san.IPAddresses
|
||||
cert, err := signCert(tmpl, issuer.Cert, priv, issuer.Key, keyType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cert.KeyType = keyType
|
||||
return &LeafCertConfig{
|
||||
CN: commonName,
|
||||
Usage: int64(usage),
|
||||
Cert: string(cert.CertPEM),
|
||||
Key: string(cert.KeyPEM),
|
||||
Algorithm: string(keyType),
|
||||
KeyLength: int64(keyBits),
|
||||
NotAfter: expire.Format("2006-01-02 15:04:05"),
|
||||
NotBefore: now.Format("2006-01-02 15:04:05"),
|
||||
CreateTime: now.Format("2006-01-02 15:04:05"),
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user