chore: move '/internal/pkg' to '/pkg'

This commit is contained in:
Fu Diwei
2025-06-17 15:54:21 +08:00
parent 30840bbba5
commit 205275b52d
611 changed files with 693 additions and 693 deletions

26
pkg/utils/cert/common.go Normal file
View File

@@ -0,0 +1,26 @@
package cert
import (
"crypto/x509"
)
// 比较两个 x509.Certificate 对象,判断它们是否是同一张证书。
// 注意,这不是精确比较,而只是基于证书序列号和数字签名的快速判断,但对于权威 CA 签发的证书来说不会存在误判。
//
// 入参:
// - a: 待比较的第一个 x509.Certificate 对象。
// - b: 待比较的第二个 x509.Certificate 对象。
//
// 出参:
// - 是否相同。
func EqualCertificate(a, b *x509.Certificate) bool {
if a == nil || b == nil {
return false
}
return string(a.Signature) == string(b.Signature) &&
a.SignatureAlgorithm == b.SignatureAlgorithm &&
a.SerialNumber.String() == b.SerialNumber.String() &&
a.Issuer.SerialNumber == b.Issuer.SerialNumber &&
a.Subject.SerialNumber == b.Subject.SerialNumber
}

View File

@@ -0,0 +1,56 @@
package cert
import (
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
)
// 将 x509.Certificate 对象转换为 PEM 编码的字符串。
//
// 入参:
// - cert: x509.Certificate 对象。
//
// 出参:
// - certPEM: 证书 PEM 内容。
// - err: 错误。
func ConvertCertificateToPEM(cert *x509.Certificate) (_certPEM string, _err error) {
if cert == nil {
return "", errors.New("`cert` is nil")
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: cert.Raw,
}
return string(pem.EncodeToMemory(block)), nil
}
// 将 ecdsa.PrivateKey 对象转换为 PEM 编码的字符串。
//
// 入参:
// - privkey: ecdsa.PrivateKey 对象。
//
// 出参:
// - privkeyPEM: 私钥 PEM 内容。
// - err: 错误。
func ConvertECPrivateKeyToPEM(privkey *ecdsa.PrivateKey) (_privkeyPEM string, _err error) {
if privkey == nil {
return "", errors.New("`privkey` is nil")
}
data, _err := x509.MarshalECPrivateKey(privkey)
if _err != nil {
return "", fmt.Errorf("failed to marshal EC private key: %w", _err)
}
block := &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: data,
}
return string(pem.EncodeToMemory(block)), nil
}

View File

@@ -0,0 +1,48 @@
package cert
import (
"encoding/pem"
"errors"
)
// 从 PEM 编码的证书字符串解析并提取服务器证书和中间证书。
//
// 入参:
// - certPEM: 证书 PEM 内容。
//
// 出参:
// - serverCertPEM: 服务器证书的 PEM 内容。
// - intermediaCertPEM: 中间证书的 PEM 内容。
// - err: 错误。
func ExtractCertificatesFromPEM(certPEM string) (_serverCertPEM string, _intermediaCertPEM string, _err error) {
pemBlocks := make([]*pem.Block, 0)
pemData := []byte(certPEM)
for {
block, rest := pem.Decode(pemData)
if block == nil || block.Type != "CERTIFICATE" {
break
}
pemBlocks = append(pemBlocks, block)
pemData = rest
}
serverCertPEM := ""
intermediaCertPEM := ""
if len(pemBlocks) == 0 {
return "", "", errors.New("failed to decode PEM block")
}
if len(pemBlocks) > 0 {
serverCertPEM = string(pem.EncodeToMemory(pemBlocks[0]))
}
if len(pemBlocks) > 1 {
for i := 1; i < len(pemBlocks); i++ {
intermediaCertPEM += string(pem.EncodeToMemory(pemBlocks[i]))
}
}
return serverCertPEM, intermediaCertPEM, nil
}

99
pkg/utils/cert/parser.go Normal file
View File

@@ -0,0 +1,99 @@
package cert
import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"github.com/go-acme/lego/v4/certcrypto"
)
// 从 PEM 编码的证书字符串解析并返回一个 x509.Certificate 对象。
// PEM 内容可能是包含多张证书的证书链,但只返回第一个证书(即服务器证书)。
//
// 入参:
// - certPEM: 证书 PEM 内容。
//
// 出参:
// - cert: x509.Certificate 对象。
// - err: 错误。
func ParseCertificateFromPEM(certPEM string) (_cert *x509.Certificate, _err error) {
pemData := []byte(certPEM)
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse certificate: %w", err)
}
return cert, nil
}
// 从 PEM 编码的私钥字符串解析并返回一个 crypto.PrivateKey 对象。
//
// 入参:
// - privkeyPEM: 私钥 PEM 内容。
//
// 出参:
// - privkey: crypto.PrivateKey 对象,可能是 rsa.PrivateKey、ecdsa.PrivateKey 或 ed25519.PrivateKey。
// - err: 错误。
func ParsePrivateKeyFromPEM(privkeyPEM string) (_privkey crypto.PrivateKey, _err error) {
pemData := []byte(privkeyPEM)
return certcrypto.ParsePEMPrivateKey(pemData)
}
// 从 PEM 编码的私钥字符串解析并返回一个 ecdsa.PrivateKey 对象。
//
// 入参:
// - privkeyPEM: 私钥 PEM 内容。
//
// 出参:
// - privkey: ecdsa.PrivateKey 对象。
// - err: 错误。
func ParseECPrivateKeyFromPEM(privkeyPEM string) (_privkey *ecdsa.PrivateKey, _err error) {
pemData := []byte(privkeyPEM)
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
privkey, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
return privkey, nil
}
// 从 PEM 编码的私钥字符串解析并返回一个 rsa.PrivateKey 对象。
//
// 入参:
// - privkeyPEM: 私钥 PEM 内容。
//
// 出参:
// - privkey: rsa.PrivateKey 对象。
// - err: 错误。
func ParsePKCS1PrivateKeyFromPEM(privkeyPEM string) (_privkey *rsa.PrivateKey, _err error) {
pemData := []byte(privkeyPEM)
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("failed to decode PEM block")
}
privkey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
return privkey, nil
}

View File

@@ -0,0 +1,87 @@
package cert
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 := ParsePrivateKeyFromPEM(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
}