package model import ( "crypto/rand" "errors" "fmt" "io" "sync" "github.com/crpt/go-crpt" _ "github.com/crpt/go-crpt/ed25519" // Import Ed25519 _ "github.com/crpt/go-crpt/sm2" // Import SM2 "go.yandata.net/iod/iod/go-trustlog/api/logger" ) // SignatureAlgorithm 定义支持的签名算法类型. type SignatureAlgorithm string const ( // SM2 国密SM2算法 SM2Algorithm SignatureAlgorithm = "sm2" // Ed25519 Ed25519算法 Ed25519Algorithm SignatureAlgorithm = "ed25519" ) // CryptoConfig 密码学配置 type CryptoConfig struct { // SignatureAlgorithm 签名算法类型 // SM2 会自动使用 SM3 哈希,Ed25519 会使用 SHA512 哈希 SignatureAlgorithm SignatureAlgorithm } var ( // 默认配置:使用 SM2(内部自动使用 SM3) defaultConfig = &CryptoConfig{ SignatureAlgorithm: SM2Algorithm, } // 全局配置 globalConfig *CryptoConfig globalConfigMutex sync.RWMutex // ErrUnsupportedAlgorithm 不支持的算法错误 ErrUnsupportedAlgorithm = errors.New("unsupported signature algorithm") ) func init() { // 自动初始化全局配置为 SM2 globalConfig = defaultConfig logger.GetGlobalLogger().Debug("Crypto config initialized with default SM2") } // SetGlobalCryptoConfig 设置全局密码学配置 func SetGlobalCryptoConfig(config *CryptoConfig) error { if config == nil { return errors.New("config cannot be nil") } // 验证配置 if err := config.Validate(); err != nil { return fmt.Errorf("invalid config: %w", err) } globalConfigMutex.Lock() defer globalConfigMutex.Unlock() globalConfig = config logger.GetGlobalLogger().Info("Global crypto config updated", "signatureAlgorithm", config.SignatureAlgorithm, ) return nil } // GetGlobalCryptoConfig 获取全局密码学配置 func GetGlobalCryptoConfig() *CryptoConfig { globalConfigMutex.RLock() defer globalConfigMutex.RUnlock() if globalConfig == nil { return defaultConfig } return globalConfig } // Validate 验证配置是否有效 func (c *CryptoConfig) Validate() error { // 验证签名算法 switch c.SignatureAlgorithm { case SM2Algorithm, Ed25519Algorithm: // 支持的算法 default: return fmt.Errorf("%w: %s", ErrUnsupportedAlgorithm, c.SignatureAlgorithm) } return nil } // toKeyType 将 SignatureAlgorithm 转换为 crpt.KeyType func (a SignatureAlgorithm) toKeyType() (crpt.KeyType, error) { switch a { case SM2Algorithm: return crpt.SM2, nil case Ed25519Algorithm: return crpt.Ed25519, nil default: return 0, fmt.Errorf("%w: %s", ErrUnsupportedAlgorithm, a) } } // KeyPair 通用密钥对,支持多种算法 type KeyPair struct { Public crpt.PublicKey `json:"publicKey"` Private crpt.PrivateKey `json:"privateKey"` Algorithm SignatureAlgorithm } // GenerateKeyPair 根据配置生成密钥对 func GenerateKeyPair(config *CryptoConfig) (*KeyPair, error) { if config == nil { config = GetGlobalCryptoConfig() } log := logger.GetGlobalLogger() log.Debug("Generating key pair", "algorithm", config.SignatureAlgorithm, ) keyType, err := config.SignatureAlgorithm.toKeyType() if err != nil { return nil, err } pub, priv, err := crpt.GenerateKey(keyType, rand.Reader) if err != nil { log.Error("Failed to generate key pair", "algorithm", config.SignatureAlgorithm, "error", err, ) return nil, fmt.Errorf("failed to generate %s key pair: %w", config.SignatureAlgorithm, err) } log.Debug("Key pair generated successfully", "algorithm", config.SignatureAlgorithm, ) return &KeyPair{ Public: pub, Private: priv, Algorithm: config.SignatureAlgorithm, }, nil } // Sign 使用密钥对签名数据 func (kp *KeyPair) Sign(data []byte, rand io.Reader) ([]byte, error) { if rand == nil { rand = defaultRand() } log := logger.GetGlobalLogger() log.Debug("Signing data", "algorithm", kp.Algorithm, "dataLength", len(data), ) signature, err := crpt.SignMessage(kp.Private, data, rand, nil) if err != nil { log.Error("Failed to sign data", "algorithm", kp.Algorithm, "error", err, ) return nil, fmt.Errorf("failed to sign with %s: %w", kp.Algorithm, err) } log.Debug("Data signed successfully", "algorithm", kp.Algorithm, "signatureLength", len(signature), ) return signature, nil } // Verify 使用公钥验证签名 func (kp *KeyPair) Verify(data, signature []byte) (bool, error) { log := logger.GetGlobalLogger() log.Debug("Verifying signature", "algorithm", kp.Algorithm, "dataLength", len(data), "signatureLength", len(signature), ) ok, err := crpt.VerifyMessage(kp.Public, data, crpt.Signature(signature), nil) if err != nil { log.Error("Failed to verify signature", "algorithm", kp.Algorithm, "error", err, ) return false, fmt.Errorf("failed to verify with %s: %w", kp.Algorithm, err) } if ok { log.Debug("Signature verified successfully", "algorithm", kp.Algorithm, ) } else { log.Warn("Signature verification failed", "algorithm", kp.Algorithm, ) } return ok, nil } // MarshalPrivateKey 序列化私钥 func (kp *KeyPair) MarshalPrivateKey() ([]byte, error) { if kp.Private == nil { return nil, errors.New("private key is nil") } return kp.Private.Bytes(), nil } // MarshalPublicKey 序列化公钥 func (kp *KeyPair) MarshalPublicKey() ([]byte, error) { if kp.Public == nil { return nil, errors.New("public key is nil") } return kp.Public.Bytes(), nil } // ParsePrivateKey 解析私钥 func ParsePrivateKey(data []byte, algorithm SignatureAlgorithm) (crpt.PrivateKey, error) { keyType, err := algorithm.toKeyType() if err != nil { return nil, err } return crpt.PrivateKeyFromBytes(keyType, data) } // ParsePublicKey 解析公钥 func ParsePublicKey(data []byte, algorithm SignatureAlgorithm) (crpt.PublicKey, error) { keyType, err := algorithm.toKeyType() if err != nil { return nil, err } return crpt.PublicKeyFromBytes(keyType, data) } // defaultRand 返回默认的随机数生成器 func defaultRand() io.Reader { return rand.Reader } // SignWithConfig 使用指定配置签名数据 func SignWithConfig(data, privateKeyDER []byte, config *CryptoConfig) ([]byte, error) { if config == nil { config = GetGlobalCryptoConfig() } log := logger.GetGlobalLogger() log.Debug("Signing with config", "algorithm", config.SignatureAlgorithm, "dataLength", len(data), ) privateKey, err := ParsePrivateKey(privateKeyDER, config.SignatureAlgorithm) if err != nil { return nil, fmt.Errorf("failed to parse private key: %w", err) } signature, err := crpt.SignMessage(privateKey, data, rand.Reader, nil) if err != nil { return nil, fmt.Errorf("failed to sign: %w", err) } log.Debug("Signed with config successfully", "algorithm", config.SignatureAlgorithm, "signatureLength", len(signature), ) return signature, nil } // VerifyWithConfig 使用指定配置验证签名 func VerifyWithConfig(data, publicKeyDER, signature []byte, config *CryptoConfig) (bool, error) { if config == nil { config = GetGlobalCryptoConfig() } log := logger.GetGlobalLogger() log.Debug("Verifying with config", "algorithm", config.SignatureAlgorithm, "dataLength", len(data), ) publicKey, err := ParsePublicKey(publicKeyDER, config.SignatureAlgorithm) if err != nil { return false, fmt.Errorf("failed to parse public key: %w", err) } ok, err := crpt.VerifyMessage(publicKey, data, crpt.Signature(signature), nil) if err != nil { return false, fmt.Errorf("failed to verify: %w", err) } log.Debug("Verified with config", "algorithm", config.SignatureAlgorithm, "result", ok, ) return ok, nil }