refactor: extract x509 transformer utils

This commit is contained in:
Fu Diwei 2024-11-18 09:12:15 +08:00
parent 295b7779ee
commit 43b2ff7957
4 changed files with 93 additions and 64 deletions

View File

@ -1,21 +1,15 @@
package deployer package deployer
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"encoding/pem"
"errors" "errors"
"fmt" "fmt"
"time"
"github.com/pavlo-v-chernykh/keystore-go/v4"
"github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/models"
"software.sslmate.com/src/go-pkcs12"
"github.com/usual2970/certimate/internal/applicant" "github.com/usual2970/certimate/internal/applicant"
"github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/utils/x509"
"github.com/usual2970/certimate/internal/utils/app" "github.com/usual2970/certimate/internal/utils/app"
) )
@ -167,57 +161,3 @@ func toStr(tag string, data any) string {
byts, _ := json.Marshal(data) byts, _ := json.Marshal(data)
return tag + "" + string(byts) return tag + "" + string(byts)
} }
func convertPEMToPFX(certificate string, privateKey string, password string) ([]byte, error) {
cert, err := x509.ParseCertificateFromPEM(certificate)
if err != nil {
return nil, err
}
privkey, err := x509.ParsePKCS1PrivateKeyFromPEM(privateKey)
if err != nil {
return nil, err
}
pfxData, err := pkcs12.LegacyRC2.Encode(privkey, cert, nil, password)
if err != nil {
return nil, err
}
return pfxData, nil
}
func convertPEMToJKS(certificate string, privateKey string, alias string, keypass string, storepass string) ([]byte, error) {
certBlock, _ := pem.Decode([]byte(certificate))
if certBlock == nil {
return nil, errors.New("failed to decode certificate PEM")
}
privkeyBlock, _ := pem.Decode([]byte(privateKey))
if privkeyBlock == nil {
return nil, errors.New("failed to decode private key PEM")
}
ks := keystore.New()
entry := keystore.PrivateKeyEntry{
CreationTime: time.Now(),
PrivateKey: privkeyBlock.Bytes,
CertificateChain: []keystore.Certificate{
{
Type: "X509",
Content: certBlock.Bytes,
},
},
}
if err := ks.SetPrivateKeyEntry(alias, entry, []byte(keypass)); err != nil {
return nil, err
}
var buf bytes.Buffer
if err := ks.Store(&buf, []byte(storepass)); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

View File

@ -11,6 +11,7 @@ import (
xerrors "github.com/pkg/errors" xerrors "github.com/pkg/errors"
"github.com/usual2970/certimate/internal/pkg/utils/fs" "github.com/usual2970/certimate/internal/pkg/utils/fs"
"github.com/usual2970/certimate/internal/pkg/utils/x509"
) )
type LocalDeployer struct { type LocalDeployer struct {
@ -73,7 +74,7 @@ func (d *LocalDeployer) Deploy(ctx context.Context) error {
d.infos = append(d.infos, toStr("保存私钥成功", nil)) d.infos = append(d.infos, toStr("保存私钥成功", nil))
case certFormatPFX: case certFormatPFX:
pfxData, err := convertPEMToPFX( pfxData, err := x509.TransformCertificateFromPEMToPFX(
d.option.Certificate.Certificate, d.option.Certificate.Certificate,
d.option.Certificate.PrivateKey, d.option.Certificate.PrivateKey,
d.option.DeployConfig.GetConfigAsString("pfxPassword"), d.option.DeployConfig.GetConfigAsString("pfxPassword"),
@ -89,7 +90,7 @@ func (d *LocalDeployer) Deploy(ctx context.Context) error {
d.infos = append(d.infos, toStr("保存证书成功", nil)) d.infos = append(d.infos, toStr("保存证书成功", nil))
case certFormatJKS: case certFormatJKS:
jksData, err := convertPEMToJKS( jksData, err := x509.TransformCertificateFromPEMToJKS(
d.option.Certificate.Certificate, d.option.Certificate.Certificate,
d.option.Certificate.PrivateKey, d.option.Certificate.PrivateKey,
d.option.DeployConfig.GetConfigAsString("jksAlias"), d.option.DeployConfig.GetConfigAsString("jksAlias"),

View File

@ -14,6 +14,7 @@ import (
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"github.com/usual2970/certimate/internal/domain" "github.com/usual2970/certimate/internal/domain"
"github.com/usual2970/certimate/internal/pkg/utils/x509"
) )
type SSHDeployer struct { type SSHDeployer struct {
@ -78,7 +79,7 @@ func (d *SSHDeployer) Deploy(ctx context.Context) error {
d.infos = append(d.infos, toStr("SSH 上传私钥成功", nil)) d.infos = append(d.infos, toStr("SSH 上传私钥成功", nil))
case certFormatPFX: case certFormatPFX:
pfxData, err := convertPEMToPFX( pfxData, err := x509.TransformCertificateFromPEMToPFX(
d.option.Certificate.Certificate, d.option.Certificate.Certificate,
d.option.Certificate.PrivateKey, d.option.Certificate.PrivateKey,
d.option.DeployConfig.GetConfigAsString("pfxPassword"), d.option.DeployConfig.GetConfigAsString("pfxPassword"),
@ -94,7 +95,7 @@ func (d *SSHDeployer) Deploy(ctx context.Context) error {
d.infos = append(d.infos, toStr("SSH 上传证书成功", nil)) d.infos = append(d.infos, toStr("SSH 上传证书成功", nil))
case certFormatJKS: case certFormatJKS:
jksData, err := convertPEMToJKS( jksData, err := x509.TransformCertificateFromPEMToJKS(
d.option.Certificate.Certificate, d.option.Certificate.Certificate,
d.option.Certificate.PrivateKey, d.option.Certificate.PrivateKey,
d.option.DeployConfig.GetConfigAsString("jksAlias"), d.option.DeployConfig.GetConfigAsString("jksAlias"),

View File

@ -0,0 +1,87 @@
package x509
import (
"bytes"
"encoding/pem"
"errors"
"time"
"github.com/pavlo-v-chernykh/keystore-go/v4"
"software.sslmate.com/src/go-pkcs12"
)
// 将 PEM 编码的证书字符串转换为 PFX 格式。
//
// 入参:
// - certPem: 证书 PEM 内容。
// - privkeyPem: 私钥 PEM 内容。
// - pfxPassword: PFX 导出密码。
//
// 出参:
// - data: PFX 格式的证书数据。
// - err: 错误。
func TransformCertificateFromPEMToPFX(certPem string, privkeyPem string, pfxPassword string) ([]byte, error) {
cert, err := ParseCertificateFromPEM(certPem)
if err != nil {
return nil, err
}
privkey, err := ParsePKCS1PrivateKeyFromPEM(privkeyPem)
if err != nil {
return nil, err
}
pfxData, err := pkcs12.LegacyRC2.Encode(privkey, cert, nil, pfxPassword)
if err != nil {
return nil, err
}
return pfxData, nil
}
// 将 PEM 编码的证书字符串转换为 JKS 格式。
//
// 入参:
// - certPem: 证书 PEM 内容。
// - privkeyPem: 私钥 PEM 内容。
// - jksAlias: JKS 别名。
// - jksKeypass: JKS 密钥密码。
// - jksStorepass: JKS 存储密码。
//
// 出参:
// - data: JKS 格式的证书数据。
// - err: 错误。
func TransformCertificateFromPEMToJKS(certPem string, privkeyPem string, jksAlias string, jksKeypass string, jksStorepass string) ([]byte, error) {
certBlock, _ := pem.Decode([]byte(certPem))
if certBlock == nil {
return nil, errors.New("failed to decode certificate PEM")
}
privkeyBlock, _ := pem.Decode([]byte(privkeyPem))
if privkeyBlock == nil {
return nil, errors.New("failed to decode private key PEM")
}
ks := keystore.New()
entry := keystore.PrivateKeyEntry{
CreationTime: time.Now(),
PrivateKey: privkeyBlock.Bytes,
CertificateChain: []keystore.Certificate{
{
Type: "X509",
Content: certBlock.Bytes,
},
},
}
if err := ks.SetPrivateKeyEntry(jksAlias, entry, []byte(jksKeypass)); err != nil {
return nil, err
}
var buf bytes.Buffer
if err := ks.Store(&buf, []byte(jksStorepass)); err != nil {
return nil, err
}
return buf.Bytes(), nil
}