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
|
|||
|
|
}
|