feat: do not encode private key to pkcs#8 when obtaining the certificate

This commit is contained in:
Fu Diwei
2026-05-29 23:47:06 +08:00
committed by RHQYZ
parent 1e001aebc6
commit cfc95399a9
3 changed files with 97 additions and 11 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ func CreateACMEAccount(ctx context.Context, config *ACMEConfig, email string) (*
return nil, err
}
keyPEM, err := xcert.ConvertECPrivateKeyToPEM(key)
keyPEM, err := xcert.ConvertECPrivateKeyToPEM(key, false)
if err != nil {
return nil, err
}
+11 -1
View File
@@ -20,6 +20,7 @@ import (
"github.com/certimate-go/certimate/internal/certacme/certifiers"
"github.com/certimate-go/certimate/internal/domain"
xcert "github.com/certimate-go/certimate/pkg/utils/cert"
)
type ObtainCertificateRequest struct {
@@ -172,11 +173,20 @@ func (c *ACMEClient) ObtainCertificate(ctx context.Context, request *ObtainCerti
}
}
// lego 自 v5 起返回的私钥 PEM 内容使用 PKCS#8 格式编码,
// 这里转换为 PKCS#1 或 SEC1 格式编码,以满足更好的兼容性。
privkeyPEM := strings.TrimSpace(string(resp.PrivateKey))
if t1, err := xcert.ParsePrivateKeyFromPEM(privkeyPEM); err == nil {
if t2, err := xcert.ConvertPrivateKeyToPEM(t1, false); err == nil {
privkeyPEM = t2
}
}
return &ObtainCertificateResponse{
CSR: strings.TrimSpace(string(resp.CSR)),
FullChainCertificate: strings.TrimSpace(string(resp.Certificate)),
IssuerCertificate: strings.TrimSpace(string(resp.IssuerCertificate)),
PrivateKey: strings.TrimSpace(string(resp.PrivateKey)),
PrivateKey: privkeyPEM,
ACMEAcctUrl: c.account.ACMEAcctUrl,
ACMECertUrl: resp.CertURL,
ARIReplaced: req.ReplacesCertID != "",
+85 -9
View File
@@ -1,7 +1,9 @@
package cert
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
@@ -28,27 +30,101 @@ func ConvertCertificateToPEM(cert *x509.Certificate) (_certPEM string, _err erro
return string(pem.EncodeToMemory(block)), nil
}
// 将 ecdsa.PrivateKey 对象转换为 PEM 编码的字符串。
// 将 rsa.PrivateKey 或 ecdsa.PrivateKey 对象转换为 PEM 编码的字符串。
//
// 入参:
// - privkey: ecdsa.PrivateKey 对象。
// - privkey: rsa.PrivateKey 或 ecdsa.PrivateKey 对象。
// - pkcs8: 是否使用 PKCS#8 格式编码。
//
// 出参:
// - privkeyPEM: 私钥 PEM 内容。
// - err: 错误。
func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey) (_privkeyPEM string, _err error) {
func ConvertPrivateKeyToPEM(privkey crypto.PrivateKey, pkcs8 bool) (_privkeyPEM string, _err error) {
if privkey == nil {
return "", fmt.Errorf("the input private key is nil")
}
data, _err := x509.MarshalECPrivateKey(privkey)
if _err != nil {
return "", fmt.Errorf("failed to marshal EC private key: %w", _err)
switch t := privkey.(type) {
case *rsa.PrivateKey:
return ConvertRSAPrivateKeyToPEM(t, pkcs8)
case *ecdsa.PrivateKey:
return ConvertECPrivateKeyToPEM(t, pkcs8)
}
block := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: data,
return "", fmt.Errorf("unknown private key type")
}
// 将 rsa.PrivateKey 对象转换为 PEM 编码的字符串。
//
// 入参:
// - privkey: rsa.PrivateKey 对象。
// - pkcs8: 是否使用 PKCS#8 格式编码。否则,使用 PKCS#1 格式编码。
//
// 出参:
// - privkeyPEM: 私钥 PEM 内容。
// - err: 错误。
func ConvertRSAPrivateKeyToPEM(privkey *rsa.PrivateKey, pkcs8 bool) (_privkeyPEM string, _err error) {
if privkey == nil {
return "", fmt.Errorf("the input private key is nil")
}
var data []byte
if pkcs8 {
data, _err = x509.MarshalPKCS8PrivateKey(privkey)
if _err != nil {
return "", fmt.Errorf("failed to marshal RSA private key: %w", _err)
}
} else {
data = x509.MarshalPKCS1PrivateKey(privkey)
if data == nil {
_err = fmt.Errorf("failed to marshal RSA private key")
return "", _err
}
}
var block *pem.Block
if pkcs8 {
block = &pem.Block{Type: "PRIVATE KEY", Bytes: data}
} else {
block = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: data}
}
return string(pem.EncodeToMemory(block)), nil
}
// 将 ecdsa.PrivateKey 对象转换为 PEM 编码的字符串。
//
// 入参:
// - privkey: ecdsa.PrivateKey 对象。
// - pkcs8: 是否使用 PKCS#8 格式编码。否则,使用 SEC1 格式编码。
//
// 出参:
// - privkeyPEM: 私钥 PEM 内容。
// - err: 错误。
func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey, pkcs8 bool) (_privkeyPEM string, _err error) {
if privkey == nil {
return "", fmt.Errorf("the input private key is nil")
}
var data []byte
if pkcs8 {
data, _err = x509.MarshalPKCS8PrivateKey(privkey)
if _err != nil {
return "", fmt.Errorf("failed to marshal EC private key: %w", _err)
}
} else {
data, _err = x509.MarshalECPrivateKey(privkey)
if _err != nil {
return "", fmt.Errorf("failed to marshal EC private key: %w", _err)
}
}
var block *pem.Block
if pkcs8 {
block = &pem.Block{Type: "PRIVATE KEY", Bytes: data}
} else {
block = &pem.Block{Type: "EC PRIVATE KEY", Bytes: data}
}
return string(pem.EncodeToMemory(block)), nil