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 }