主要更新: 1. 数据库持久化功能 - 支持三种策略:仅落库、既落库又存证、仅存证 - 实现 Cursor Worker 异步扫描和存证机制 - 实现 Retry Worker 失败重试机制 - 支持 PostgreSQL、MySQL、SQLite 等多种数据库 - 添加 ClientIP 和 ServerIP 字段(可空,仅落库) 2. 集群并发安全 - 使用 SELECT FOR UPDATE SKIP LOCKED 防止重复处理 - 实现 CAS (Compare-And-Set) 原子状态更新 - 添加 updated_at 字段支持并发控制 3. Cursor 初始化优化 - 自动基于历史数据初始化 cursor - 确保不遗漏任何历史记录 - 修复 UPSERT 逻辑 4. 测试完善 - 添加 E2E 集成测试(含 Pulsar 消费者验证) - 添加 PostgreSQL 集成测试 - 添加 Pulsar 集成测试 - 添加集群并发安全测试 - 添加 Cursor 初始化验证测试 - 补充大量单元测试,提升覆盖率 5. 工具脚本 - 添加数据库迁移脚本 - 添加 Cursor 状态检查工具 - 添加 Cursor 初始化工具 - 添加 Pulsar 消息验证工具 6. 文档清理 - 删除冗余文档,只保留根目录 README 测试结果: - 所有 E2E 测试通过(100%) - 数据库持久化与异步存证流程验证通过 - 集群环境下的并发安全性验证通过 - Cursor 自动初始化和历史数据处理验证通过
208 lines
5.6 KiB
Go
208 lines
5.6 KiB
Go
package model
|
||
|
||
import (
|
||
"fmt"
|
||
|
||
"github.com/crpt/go-crpt"
|
||
_ "github.com/crpt/go-crpt/ed25519" // 注册 Ed25519
|
||
_ "github.com/crpt/go-crpt/sm2" // 注册 SM2
|
||
|
||
"go.yandata.net/iod/iod/go-trustlog/api/logger"
|
||
)
|
||
|
||
// ConfigSigner 基于配置的通用签名器
|
||
// 根据 CryptoConfig 自动使用对应的签名算法
|
||
type ConfigSigner struct {
|
||
privateKey []byte // 私钥(序列化格式)
|
||
publicKey []byte // 公钥(序列化格式)
|
||
config *CryptoConfig // 密码学配置
|
||
privKey crpt.PrivateKey // 解析后的私钥
|
||
pubKey crpt.PublicKey // 解析后的公钥
|
||
}
|
||
|
||
// NewConfigSigner 创建基于配置的签名器
|
||
// 如果 config 为 nil,则使用全局配置
|
||
func NewConfigSigner(privateKey, publicKey []byte, config *CryptoConfig) (*ConfigSigner, error) {
|
||
if config == nil {
|
||
config = GetGlobalCryptoConfig()
|
||
}
|
||
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Creating ConfigSigner",
|
||
"algorithm", config.SignatureAlgorithm,
|
||
"privateKeyLength", len(privateKey),
|
||
"publicKeyLength", len(publicKey),
|
||
)
|
||
|
||
signer := &ConfigSigner{
|
||
privateKey: privateKey,
|
||
publicKey: publicKey,
|
||
config: config,
|
||
}
|
||
|
||
// 延迟解析密钥,只在需要时解析
|
||
// 这样可以避免初始化顺序问题
|
||
|
||
log.Debug("ConfigSigner created successfully",
|
||
"algorithm", config.SignatureAlgorithm,
|
||
)
|
||
|
||
return signer, nil
|
||
}
|
||
|
||
// NewDefaultSigner 创建使用默认 SM2 算法的签名器
|
||
// 注意:总是使用 SM2,不受全局配置影响
|
||
func NewDefaultSigner(privateKey, publicKey []byte) (*ConfigSigner, error) {
|
||
sm2Config := &CryptoConfig{
|
||
SignatureAlgorithm: SM2Algorithm,
|
||
}
|
||
return NewConfigSigner(privateKey, publicKey, sm2Config)
|
||
}
|
||
|
||
// Sign 对数据进行签名
|
||
func (s *ConfigSigner) Sign(data []byte) ([]byte, error) {
|
||
if len(s.privateKey) == 0 {
|
||
return nil, fmt.Errorf("private key is not set")
|
||
}
|
||
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Signing with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"dataLength", len(data),
|
||
)
|
||
|
||
// 根据算法类型使用对应的方法
|
||
switch s.config.SignatureAlgorithm {
|
||
case SM2Algorithm:
|
||
// SM2 使用现有的 ComputeSignature 函数(兼容 DER 格式)
|
||
signature, err := ComputeSignature(data, s.privateKey)
|
||
if err != nil {
|
||
log.Error("Failed to sign with SM2",
|
||
"error", err,
|
||
)
|
||
return nil, err
|
||
}
|
||
log.Debug("Signed successfully with SM2",
|
||
"signatureLength", len(signature),
|
||
)
|
||
return signature, nil
|
||
|
||
default:
|
||
// 其他算法使用 crpt 通用接口
|
||
// 懒加载:解析私钥
|
||
if s.privKey == nil {
|
||
keyType, err := s.config.SignatureAlgorithm.toKeyType()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
privKey, err := crpt.PrivateKeyFromBytes(keyType, s.privateKey)
|
||
if err != nil {
|
||
log.Error("Failed to parse private key",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"error", err,
|
||
)
|
||
return nil, fmt.Errorf("failed to parse private key: %w", err)
|
||
}
|
||
s.privKey = privKey
|
||
}
|
||
|
||
signature, err := crpt.SignMessage(s.privKey, data, nil, nil)
|
||
if err != nil {
|
||
log.Error("Failed to sign with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"error", err,
|
||
)
|
||
return nil, fmt.Errorf("failed to sign: %w", err)
|
||
}
|
||
|
||
log.Debug("Signed successfully with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"signatureLength", len(signature),
|
||
)
|
||
|
||
return signature, nil
|
||
}
|
||
}
|
||
|
||
// Verify 验证签名
|
||
func (s *ConfigSigner) Verify(data, signature []byte) (bool, error) {
|
||
if len(s.publicKey) == 0 {
|
||
return false, fmt.Errorf("public key is not set")
|
||
}
|
||
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Verifying with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"dataLength", len(data),
|
||
"signatureLength", len(signature),
|
||
)
|
||
|
||
// 根据算法类型使用对应的方法
|
||
switch s.config.SignatureAlgorithm {
|
||
case SM2Algorithm:
|
||
// SM2 使用现有的 VerifySignature 函数(兼容 DER 格式)
|
||
ok, err := VerifySignature(data, s.publicKey, signature)
|
||
if err != nil {
|
||
// VerifySignature 在验证失败时也返回错误,需要判断错误类型
|
||
// 如果是 "signature verification failed",则返回 (false, nil)
|
||
if ok == false {
|
||
// 验证失败(不是异常)
|
||
log.Warn("Verification failed with SM2")
|
||
return false, nil
|
||
}
|
||
// 其他错误(如解析错误)
|
||
log.Error("Failed to verify with SM2", "error", err)
|
||
return false, err
|
||
}
|
||
log.Debug("Verified successfully with SM2")
|
||
return true, nil
|
||
|
||
default:
|
||
// 其他算法使用 crpt 通用接口
|
||
// 懒加载:解析公钥
|
||
if s.pubKey == nil {
|
||
keyType, err := s.config.SignatureAlgorithm.toKeyType()
|
||
if err != nil {
|
||
return false, err
|
||
}
|
||
|
||
pubKey, err := crpt.PublicKeyFromBytes(keyType, s.publicKey)
|
||
if err != nil {
|
||
log.Error("Failed to parse public key",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"error", err,
|
||
)
|
||
return false, fmt.Errorf("failed to parse public key: %w", err)
|
||
}
|
||
s.pubKey = pubKey
|
||
}
|
||
|
||
ok, err := crpt.VerifyMessage(s.pubKey, data, crpt.Signature(signature), nil)
|
||
if err != nil {
|
||
log.Error("Failed to verify with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
"error", err,
|
||
)
|
||
return false, fmt.Errorf("failed to verify: %w", err)
|
||
}
|
||
|
||
if ok {
|
||
log.Debug("Verified successfully with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
)
|
||
} else {
|
||
log.Warn("Verification failed with ConfigSigner",
|
||
"algorithm", s.config.SignatureAlgorithm,
|
||
)
|
||
}
|
||
|
||
return ok, nil
|
||
}
|
||
}
|
||
|
||
// GetAlgorithm 获取签名器使用的算法
|
||
func (s *ConfigSigner) GetAlgorithm() SignatureAlgorithm {
|
||
return s.config.SignatureAlgorithm
|
||
}
|