以下是一个使用 Go 语言编写的简单示例,根据传入的 p10(可能对应的是 SM2、RSA2048 或 RSA4096),通过本地的 RSA 根证书或 SM2 根证书签发出相应证书的 CA 服务:
package main
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"log"
"math/big"
"os"
"time"
"github.com/tjfoc/gmsm/sm2"
bccrypto "github.com/btcsuite/btcutil/base58check" // Base58Check 编码
)
func main() {
p10 := "<传入的 P10 请求>"
cert, err := signCertificate(p10)
if err != nil {
log.Fatal(err)
}
err = saveCertificate(cert)
if err != nil {
log.Fatal(err)
}
fmt.Println("证书签发成功")
}
// 使用本地根证书签发新证书
func signCertificate(p10 string) ([]byte, error) {
rootCertPEM := "<根证书 PEM>"
rootKeyPEM := "<根证书私钥 PEM>"
block, _ := pem.Decode([]byte(rootCertPEM))
if block == nil {
return nil, fmt.Errorf("failed to decode root certificate")
}
rootCert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse root certificate: %w", err)
}
block, _ = pem.Decode([]byte(rootKeyPEM))
if block == nil {
return nil, fmt.Errorf("failed to decode root private key")
}
rootKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse root private key: %w", err)
}
template := &x509.CertificateRequest{
RawSubjectPublicKeyInfo: []byte(p10),
}
certDER, err := x509.CreateCertificateRequest(rand.Reader, template, rootKey)
if err != nil {
return nil, fmt.Errorf("failed to create certificate request: %w", err)
}
block = &pem.Block{
Type: "CERTIFICATE",
Bytes: certDER,
}
pemCert := pem.EncodeToMemory(block)
signedCert, err := x509.ParseCertificateRequest(certDER)
if err != nil {
return nil, fmt.Errorf("failed to parse signed certificate request: %w", err)
}
parentTemplate := &x509.Certificate{
SerialNumber: big.NewInt(2),
Issuer: rootCert.Subject,
Subject: signedCert.Subject,
PublicKeyAlgorithm: signedCert.PublicKeyAlgorithm,
PublicKey: signedCert.PublicKey,
KeyUsage : x509.KeyUsageDigitalSignature|x509.KeyUsageContentCommitment|x509.KeyUsageDataEncipherment|x509.KeyUsageKeyAgreement|
x509.KeyUsageCertSign | x509.KeyUsageCRLSign ,
ExtKeyUsage : []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
BasicConstraintsValid:true
S
return pemCert, nil
}
// 将签发的证书保存到文件中
func saveCertificate(cert []byte) error {
fileName := "<要保存的证书文件名>"
f, err := os.Create(fileName)
if err != nil {
return fmt.Errorf("failed to create certificate file: %w", err)
}
defer f.Close()
_, err = f.Write(cert)
if err != nil {
return fmt.Errorf("failed to write certificate to file: %w", err)
}
return nil
}
请替换 <根证书 PEM>、<根证书私钥 PEM>、<传入的 P10 请求> 和 <要保存的证书文件名> 为相应的值。
需要注意,该示例使用了 gmsm/sm2 和 btcsuite/btcutil/base58check 这两个库。你可以在项目中添加相应的依赖并导入这些包。此外,该示例假设根证书和私钥已经存在,并且是 PEM 编码格式。
请确保你具备签发证书所需的私钥权限,并妥善保护私钥和相关敏感信息。另外,在实际应用中,还需根据具体需求进行适当的修改和完善,包括对证书请求进行验证、设置有效期限、扩展字段等。
内容由零声教学AI助手提供,问题来源于学员提问




