Files
Logan.Li b0b611eee2
CI / backend (push) Canceled after 0s
refactor(payment): 支付配置接入统一 secretbox 信封加密
- 丢弃支付模块自带的 PAYMENT_SECRET_KEY/JWT_SECRET 派生双密钥体系,
  EncryptSecret/DecryptSecret 直接走 internal/secretbox(OPSLIC_MASTER_KEY)
- 全站只有一把主密钥:Waffo 私钥、节点 shared_key、支付 APIv3 密钥/应用私钥同格式同前缀
- 测试改由 TestMain 装载 secretbox 主密钥,密文前缀统一引用 secretbox.Prefix
- .env.example 移除 PAYMENT_SECRET_KEY,改为说明复用 OPSLIC_MASTER_KEY
2026-11-01 06:03:24 +08:00

107 lines
2.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package payment
import (
"backend/internal/secretbox"
"crypto/sha256"
"encoding/hex"
"strings"
)
// 支付配置敏感字段的加密出口:统一走项目级信封加密(internal/secretbox,AES-256-GCM)。
//
// 这样全站只有一把主密钥(环境变量 OPSLIC_MASTER_KEY,启动时 fail-fast 装载),
// 支付配置不再自带第二套密钥体系:微信 APIv3 密钥、支付宝应用私钥/公钥
// 与 Waffo 私钥、节点 shared_key 共用同一套密文格式(enc:v1: 前缀)。 // Logan.Li
const (
// EnvPaymentMasterKey 主密钥环境变量名(与 secretbox 一致,保留常量供文档/提示引用) // Logan.Li
EnvPaymentMasterKey = "OPSLIC_MASTER_KEY"
)
// PaymentMasterKeyOrigin 返回加密主密钥来源,供后台页面提示 // Logan.Li
func PaymentMasterKeyOrigin() string {
if secretbox.Ready() {
return "env"
}
return "none"
}
// EncryptSecret 加密敏感字段;空串直接返回空串 // Logan.Li
func EncryptSecret(plain string) (string, error) {
if strings.TrimSpace(plain) == "" {
return "", nil
}
return secretbox.Encrypt(plain)
}
// DecryptSecret 解密敏感字段;无前缀视为历史明文直接返回 // Logan.Li
func DecryptSecret(stored string) (string, error) {
raw := strings.TrimSpace(stored)
if raw == "" {
return "", nil
}
return secretbox.Decrypt(raw)
}
// MaskTail 脱敏展示:仅保留末尾 keep 位,其余用掩码填充到 total 位 // Logan.Li
func MaskTail(secret string, keep, total int) string {
s := strings.TrimSpace(secret)
if s == "" {
return ""
}
if total <= 0 {
total = len(s)
}
if total < keep {
total = keep
}
if len(s) <= keep {
return strings.Repeat("•", total-len(s)) + s
}
return strings.Repeat("•", total-keep) + s[len(s)-keep:]
}
// FingerprintSHA256 计算内容指纹,用于「已配置但不回显」字段 // Logan.Li
func FingerprintSHA256(data []byte) string {
if len(data) == 0 {
return ""
}
sum := sha256.Sum256(data)
return hex.EncodeToString(sum[:])
}
// ShortFingerprint 指纹取前 16 位做展示 // Logan.Li
func ShortFingerprint(fp string) string {
if len(fp) <= 16 {
return fp
}
return fp[:16]
}
// NormalizePEM 把可能是裸 base64 的密钥补全成 PEM 块 // Logan.Li
func NormalizePEM(raw, begin, end string) string {
s := strings.TrimSpace(raw)
if s == "" {
return ""
}
// 已含 PEM 头则原样(统一换行)
if strings.Contains(s, "-----BEGIN") {
return strings.ReplaceAll(s, "\r\n", "\n")
}
body := strings.Join(strings.Fields(s), "")
var b strings.Builder
b.WriteString(begin)
b.WriteString("\n")
for i := 0; i < len(body); i += 64 {
j := i + 64
if j > len(body) {
j = len(body)
}
b.WriteString(body[i:j])
b.WriteString("\n")
}
b.WriteString(end)
b.WriteString("\n")
return b.String()
}