Files
go-trustlog/api/model/signer.go
ryan 4b72a37120 feat: 完善数据库持久化与存证功能
主要更新:

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 自动初始化和历史数据处理验证通过
2025-12-24 15:31:11 +08:00

162 lines
4.7 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 model
import (
"bytes"
"go.yandata.net/iod/iod/go-trustlog/api/logger"
)
// Signer 签名器接口,用于抽象不同的签名算法实现。
// 实现了此接口的类型可以提供签名和验签功能。
//
// SDK 默认使用 SM2 算法(内部自动使用 SM3 哈希)。
// 可通过 SetGlobalCryptoConfig 切换到其他算法(如 Ed25519
type Signer interface {
// Sign 对数据进行签名。
// 参数:
// - data: 待签名的原始数据
// 返回: 签名字节数组和可能的错误
Sign(data []byte) ([]byte, error)
// Verify 验证签名。
// 参数:
// - data: 原始数据
// - signature: 签名字节数组
//
// 返回: 验证是否成功和可能的错误
Verify(data, signature []byte) (bool, error)
}
// SM2Signer SM2签名器实现。
// 使用SM2算法进行签名和验签内部自动使用 SM3 哈希)。
//
// 这是 SDK 的默认签名算法。如需使用其他算法,请使用 ConfigSigner。
type SM2Signer struct {
privateKey []byte // 私钥DER编码格式
publicKey []byte // 公钥DER编码格式
}
// NewSM2Signer 创建新的SM2签名器。
// 这是 SDK 默认推荐的签名器,使用 SM2 算法(内部自动使用 SM3 哈希)。
//
// 参数:
// - privateKey: 私钥DER编码格式用于签名
// - publicKey: 公钥DER编码格式用于验签
//
// 示例:
//
// keyPair, _ := model.GenerateSM2KeyPair()
// privateKeyDER, _ := model.MarshalSM2PrivateDER(keyPair.Private)
// publicKeyDER, _ := model.MarshalSM2PublicDER(keyPair.Public)
// signer := model.NewSM2Signer(privateKeyDER, publicKeyDER)
func NewSM2Signer(privateKey, publicKey []byte) *SM2Signer {
log := logger.GetGlobalLogger()
log.Debug("Creating new SM2 signer (default algorithm, uses SM3 hash)",
"privateKeyLength", len(privateKey),
"publicKeyLength", len(publicKey),
)
return &SM2Signer{
privateKey: privateKey,
publicKey: publicKey,
}
}
// Sign 使用SM2私钥对数据进行签名内部使用 SM3 哈希)。
func (s *SM2Signer) Sign(data []byte) ([]byte, error) {
log := logger.GetGlobalLogger()
log.Debug("Signing data with SM2 (using SM3 hash)",
"dataLength", len(data),
"privateKeyLength", len(s.privateKey),
)
signature, err := ComputeSignature(data, s.privateKey)
if err != nil {
log.Error("Failed to sign data with SM2",
"error", err,
"dataLength", len(data),
)
return nil, err
}
log.Debug("Data signed successfully with SM2",
"dataLength", len(data),
"signatureLength", len(signature),
)
return signature, nil
}
// Verify 使用SM2公钥验证签名内部使用 SM3 哈希)。
// 注意: go-crpt 库会自动使用 SM3 算法计算摘要并验证。
// 返回: 验证是否成功和可能的错误.
func (s *SM2Signer) Verify(data, signature []byte) (bool, error) {
log := logger.GetGlobalLogger()
log.Debug("Verifying signature with SM2",
"dataLength", len(data),
"signatureLength", len(signature),
"publicKeyLength", len(s.publicKey),
)
valid, err := VerifySignature(data, s.publicKey, signature)
if err != nil {
log.Error("Failed to verify signature with SM2",
"error", err,
"dataLength", len(data),
"signatureLength", len(signature),
)
return false, err
}
if valid {
log.Debug("Signature verified successfully with SM2",
"dataLength", len(data),
)
} else {
log.Warn("Signature verification failed with SM2",
"dataLength", len(data),
"signatureLength", len(signature),
)
}
return valid, nil
}
// NopSigner 空操作签名器实现。
// 对原hash不做任何操作直接返回原数据。
// 适用于不需要实际签名操作的场景,如测试或某些特殊用途。
type NopSigner struct{}
// NewNopSigner 创建新的空操作签名器。
func NewNopSigner() *NopSigner {
log := logger.GetGlobalLogger()
log.Debug("Creating new NopSigner")
return &NopSigner{}
}
// Sign 直接返回原数据的副本,不做任何签名操作。
func (n *NopSigner) Sign(data []byte) ([]byte, error) {
log := logger.GetGlobalLogger()
log.Debug("NopSigner: signing data (returning copy)",
"dataLength", len(data),
)
// 返回数据副本
result := make([]byte, len(data))
copy(result, data)
return result, nil
}
// Verify 验证签名是否等于原数据。
func (n *NopSigner) Verify(data, signature []byte) (bool, error) {
log := logger.GetGlobalLogger()
log.Debug("NopSigner: verifying signature",
"dataLength", len(data),
"signatureLength", len(signature),
)
valid := bytes.Equal(data, signature)
if valid {
log.Debug("NopSigner: signature verified successfully",
"dataLength", len(data),
)
} else {
log.Warn("NopSigner: signature verification failed",
"dataLength", len(data),
"signatureLength", len(signature),
)
}
return valid, nil
}