From 5b7245a78de11574ad2cbd870eb5d1b8d3972501 Mon Sep 17 00:00:00 2001 From: v-me-50 Date: Wed, 17 Sep 2025 15:35:18 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E5=AE=9D?= =?UTF-8?q?=E5=A1=94dns=20=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91=E6=9F=A5?= =?UTF-8?q?=E7=9C=8B=E8=AF=81=E4=B9=A6=E4=BA=8E=E4=B8=8B=E8=BD=BD=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E5=86=85=E5=AE=B9=E4=B8=8D=E4=B8=80=E8=87=B4=20?= =?UTF-8?q?=E3=80=90=E4=BF=AE=E5=A4=8D=E3=80=91=E5=A4=9A=E4=B8=AAca?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E9=80=89=E4=B8=AD=20=E3=80=90=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=88=9B=E5=BB=BA=E4=B8=AD=E9=97=B4=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E7=A7=81=E6=9C=89ca=E5=8A=A0=E5=AF=86=E7=AE=97?= =?UTF-8?q?=E6=B3=95=E6=B2=A1=E6=9C=89=E9=BB=98=E8=AE=A4=E7=BB=A7=E6=89=BF?= =?UTF-8?q?=20=E3=80=90=E8=B0=83=E6=95=B4=E3=80=91=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E8=87=AA=E7=AD=BE=E8=AF=81=E4=B9=A6=E9=99=84=E5=B8=A6pfx?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/private_ca/private_ca.go | 30 ++++++++++++++++++++++++ backend/internal/cert/apply/apply.go | 11 +++++++++ backend/migrations/init.go | 2 ++ backend/public/cert.go | 9 ++++--- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/backend/app/api/private_ca/private_ca.go b/backend/app/api/private_ca/private_ca.go index 9d4f3f6..ec60d91 100644 --- a/backend/app/api/private_ca/private_ca.go +++ b/backend/app/api/private_ca/private_ca.go @@ -162,6 +162,10 @@ func DownloadCert(c *gin.Context) { public.FailMsg(c, err.Error()) return } + if certData == nil { + public.FailMsg(c, "证书不存在") + return + } // 构建 zip 包(内存中) buf := new(bytes.Buffer) @@ -213,6 +217,32 @@ func DownloadCert(c *gin.Context) { } } + if certData["algorithm"] == "ecdsa" || certData["algorithm"] == "rsa" { + // cert.pfx + pfxPassword := "allinssl" + pfxData, err := public.PEMToPFX(certStr, keyStr, pfxPassword) + if err == nil && len(pfxData) > 0 { + pfxWriter, err := zipWriter.Create("IIS/cert.pfx") + if err != nil { + public.FailMsg(c, err.Error()) + return + } + if _, err := pfxWriter.Write(pfxData); err != nil { + public.FailMsg(c, err.Error()) + return + } + txtWriter, err := zipWriter.Create("IIS/passwd.txt") + if err != nil { + public.FailMsg(c, err.Error()) + return + } + if _, err := txtWriter.Write([]byte(pfxPassword)); err != nil { + public.FailMsg(c, err.Error()) + return + } + } + } + // 关闭 zipWriter if err := zipWriter.Close(); err != nil { public.FailMsg(c, err.Error()) diff --git a/backend/internal/cert/apply/apply.go b/backend/internal/cert/apply/apply.go index f9b5fd7..30bbfad 100644 --- a/backend/internal/cert/apply/apply.go +++ b/backend/internal/cert/apply/apply.go @@ -3,6 +3,7 @@ package apply import ( "ALLinSSL/backend/internal/access" "ALLinSSL/backend/internal/cert" + "ALLinSSL/backend/internal/cert/apply/lego/bt" "ALLinSSL/backend/internal/cert/apply/lego/jdcloud" "ALLinSSL/backend/internal/cert/apply/lego/webhook" "ALLinSSL/backend/public" @@ -216,6 +217,16 @@ func GetDNSProvider(providerName string, creds map[string]string, httpClient *ht config.APISecret = creds["api_secret"] config.PropagationTimeout = maxWait return spaceship.NewDNSProviderConfig(config) + case "btdomain": + config := bt.NewDefaultConfig() + config.AccountID = creds["account_id"] + config.AccessKey = creds["access_key"] + config.SecretKey = creds["secret_key"] + if creds["base_url"] != "" { + config.BaseURL = creds["base_url"] + } + config.PropagationTimeout = maxWait + return bt.NewDNSProviderConfig(config) //case "edgeone": //config := diff --git a/backend/migrations/init.go b/backend/migrations/init.go index 823a248..d218253 100644 --- a/backend/migrations/init.go +++ b/backend/migrations/init.go @@ -190,6 +190,8 @@ func init() { InsertIfNotExists(db, "access_type", map[string]any{"name": "webhook", "type": "dns"}, []string{"name", "type"}, []any{"webhook", "dns"}) InsertIfNotExists(db, "access_type", map[string]any{"name": "webhook", "type": "host"}, []string{"name", "type"}, []any{"webhook", "host"}) + InsertIfNotExists(db, "access_type", map[string]any{"name": "btdomain", "type": "dns"}, []string{"name", "type"}, []any{"btdomain", "dns"}) + err = sqlite_migrate.EnsureDatabaseWithTables( "data/site_monitor.db", "data/data.db", diff --git a/backend/public/cert.go b/backend/public/cert.go index 06cecb3..d25d6cb 100644 --- a/backend/public/cert.go +++ b/backend/public/cert.go @@ -168,18 +168,21 @@ func PEMToPFX(certPEM, keyPEM, pfxPassword string) ([]byte, error) { return nil, fmt.Errorf("解析证书失败: %v", err) } - // 尝试解析私钥(PKCS8或PKCS1格式) + // 尝试解析私钥(PKCS8、PKCS1 或 EC 格式) var privKey interface{} privKey, err = x509.ParsePKCS8PrivateKey(keyBlock.Bytes) if err != nil { privKey, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes) if err != nil { - return nil, fmt.Errorf("解析私钥失败: %v", err) + privKey, err = x509.ParseECPrivateKey(keyBlock.Bytes) + if err != nil { + return nil, fmt.Errorf("解析私钥失败: %v", err) + } } } // 编码为PFX格式 - pfxData, err := pkcs12.Encode(rand.Reader, privKey, cert, nil, pfxPassword) + pfxData, err := pkcs12.LegacyRC2.WithRand(rand.Reader).Encode(privKey, cert, nil, pfxPassword) if err != nil { return nil, fmt.Errorf("编码PFX失败: %v", err) }