- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录 - 更新README中所有import路径从trustlog-sdk改为go-trustlog - 更新cookiecutter配置文件中的项目名称 - 更新根目录.lefthook.yml以引用新位置的配置 - 添加go.sum文件到版本控制 - 删除过时的示例文件 这次重构与trustlog-server保持一致的目录结构, 为未来支持多语言SDK(Python、Java等)预留空间。
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/trustlog-sdk/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
|
||
}
|