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