- go.yandata.net/iod/iod/go-trustlog → go.yandata.net/wangsiyuan/go-trustlog - 更新 go.mod module声明 - 更新 README.md 安装说明 - 批量更新所有 .go 文件中的 import 路径 - 61个文件受影响 这样go-trustlog可以作为独立SDK使用
394 lines
12 KiB
Go
394 lines
12 KiB
Go
package model
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"errors"
|
||
"fmt"
|
||
|
||
"github.com/crpt/go-crpt"
|
||
_ "github.com/crpt/go-crpt/sm2" // Import SM2 to register it
|
||
|
||
"go.yandata.net/wangsiyuan/go-trustlog/api/logger"
|
||
)
|
||
|
||
var (
|
||
ErrPrivateKeyIsNil = errors.New("private key is nil")
|
||
ErrPublicAndKeysNotMatch = errors.New("public and private keys don't match")
|
||
)
|
||
|
||
// ComputeSignature 计算SM2签名.
|
||
// 这是 SDK 默认的签名函数,使用 SM2 算法(内部自动使用 SM3 哈希)。
|
||
//
|
||
// 参数:
|
||
// - data: 待签名的原始数据
|
||
// - privateKeyDER: 私钥的DER编码字节数组
|
||
//
|
||
// 返回: 签名字节数组.
|
||
// 注意: go-crpt 库会自动使用 SM3 算法计算摘要并签名。
|
||
func ComputeSignature(data, privateKeyDER []byte) ([]byte, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Computing SM2 signature",
|
||
"dataLength", len(data),
|
||
"privateKeyDERLength", len(privateKeyDER),
|
||
)
|
||
|
||
if len(privateKeyDER) == 0 {
|
||
log.Error("Private key is empty")
|
||
return nil, errors.New("private key cannot be empty")
|
||
}
|
||
|
||
if len(data) == 0 {
|
||
log.Error("Data to sign is empty")
|
||
return nil, errors.New("data to sign cannot be empty")
|
||
}
|
||
|
||
// 解析DER格式的私钥
|
||
log.Debug("Parsing SM2 private key from DER format")
|
||
privateKey, err := crpt.PrivateKeyFromBytes(crpt.SM2, privateKeyDER)
|
||
if err != nil {
|
||
log.Error("Failed to parse SM2 private key",
|
||
"error", err,
|
||
"keyLength", len(privateKeyDER),
|
||
)
|
||
return nil, fmt.Errorf("failed to parse SM2 private key (key length: %d): %w", len(privateKeyDER), err)
|
||
}
|
||
|
||
if privateKey == nil {
|
||
log.Error("Parsed private key is nil")
|
||
return nil, ErrPrivateKeyIsNil
|
||
}
|
||
|
||
// 使用SM2签名(ASN.1编码),go-crpt 库会自动使用 SM3 计算摘要
|
||
log.Debug("Signing raw data with SM2 using ASN.1 encoding (SM3 hash)")
|
||
signature, err := crpt.SignMessage(privateKey, data, rand.Reader, nil)
|
||
if err != nil {
|
||
log.Error("Failed to sign data with SM2",
|
||
"error", err,
|
||
"dataLength", len(data),
|
||
)
|
||
return nil, fmt.Errorf("failed to sign data with SM2 (data length: %d): %w", len(data), err)
|
||
}
|
||
|
||
log.Debug("SM2 signature computed successfully",
|
||
"dataLength", len(data),
|
||
"signatureLength", len(signature),
|
||
)
|
||
return signature, nil
|
||
}
|
||
|
||
// VerifySignature 验证SM2签名.
|
||
// 这是 SDK 默认的验签函数,使用 SM2 算法(内部自动使用 SM3 哈希)。
|
||
//
|
||
// 参数:
|
||
// - data: 原始数据
|
||
// - publicKeyDER: 公钥的DER编码字节数组
|
||
// - signature: 签名字节数组
|
||
//
|
||
// 返回: 验证是否成功和可能的错误.
|
||
// 注意: go-crpt 库会自动使用 SM3 算法计算摘要并验证。
|
||
func VerifySignature(data, publicKeyDER, signature []byte) (bool, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Verifying SM2 signature",
|
||
"dataLength", len(data),
|
||
"publicKeyDERLength", len(publicKeyDER),
|
||
"signatureLength", len(signature),
|
||
)
|
||
|
||
if len(publicKeyDER) == 0 {
|
||
log.Error("Public key is empty")
|
||
return false, errors.New("public key cannot be empty")
|
||
}
|
||
|
||
if len(data) == 0 {
|
||
log.Error("Data to verify is empty")
|
||
return false, errors.New("data to verify cannot be empty")
|
||
}
|
||
|
||
if len(signature) == 0 {
|
||
log.Error("Signature is empty")
|
||
return false, errors.New("signature cannot be empty")
|
||
}
|
||
|
||
// 解析DER格式的公钥,复用ParseSM2PublicDER以避免代码重复
|
||
log.Debug("Parsing SM2 public key from DER format")
|
||
publicKey, err := ParseSM2PublicDER(publicKeyDER)
|
||
if err != nil {
|
||
log.Error("Failed to parse SM2 public key",
|
||
"error", err,
|
||
"keyLength", len(publicKeyDER),
|
||
)
|
||
return false, fmt.Errorf("failed to parse SM2 public key (key length: %d): %w", len(publicKeyDER), err)
|
||
}
|
||
|
||
// 验证签名(ASN.1编码),go-crpt 库会自动使用 SM3 计算摘要
|
||
log.Debug("Verifying signature with SM2 using ASN.1 encoding (SM3 hash)")
|
||
ok, err := crpt.VerifyMessage(publicKey, data, crpt.Signature(signature), nil)
|
||
if err != nil {
|
||
log.Error("Failed to verify SM2 signature",
|
||
"error", err,
|
||
"dataLength", len(data),
|
||
"signatureLength", len(signature),
|
||
)
|
||
return false, fmt.Errorf("failed to verify signature: %w", err)
|
||
}
|
||
if !ok {
|
||
log.Warn("SM2 signature verification failed",
|
||
"dataLength", len(data),
|
||
"signatureLength", len(signature),
|
||
)
|
||
return false, fmt.Errorf(
|
||
"signature verification failed (data length: %d, signature length: %d)",
|
||
len(data), len(signature),
|
||
)
|
||
}
|
||
log.Debug("SM2 signature verified successfully",
|
||
"dataLength", len(data),
|
||
)
|
||
return true, nil
|
||
}
|
||
|
||
// GenerateSM2KeyPair 生成SM2密钥对.
|
||
// 这是 SDK 默认推荐的密钥生成方法。
|
||
//
|
||
// 返回新生成的密钥对,包含公钥和私钥.
|
||
// SM2 算法会在签名时自动使用 SM3 哈希。
|
||
func GenerateSM2KeyPair() (*SM2KeyPair, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Generating SM2 key pair")
|
||
pub, priv, err := crpt.GenerateKey(crpt.SM2, rand.Reader)
|
||
if err != nil {
|
||
log.Error("Failed to generate SM2 key pair", "error", err)
|
||
return nil, fmt.Errorf("failed to generate SM2 key pair: %w", err)
|
||
}
|
||
|
||
if priv == nil {
|
||
log.Error("Generated private key is nil")
|
||
return nil, errors.New("generated private key is nil")
|
||
}
|
||
|
||
log.Debug("SM2 key pair generated successfully")
|
||
return &SM2KeyPair{
|
||
Public: pub,
|
||
Private: priv,
|
||
}, nil
|
||
}
|
||
|
||
// SM2KeyPair SM2密钥对,包含公钥和私钥.
|
||
type SM2KeyPair struct {
|
||
Public crpt.PublicKey `json:"publicKey"`
|
||
Private crpt.PrivateKey `json:"privateKey"`
|
||
}
|
||
|
||
// MarshalSM2PrivateDER 将私钥编码为DER格式.
|
||
// 将SM2私钥转换为DER格式的字节数组,用于存储或传输.
|
||
func MarshalSM2PrivateDER(priv crpt.PrivateKey) ([]byte, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Marshaling SM2 private key to DER format")
|
||
if priv == nil {
|
||
log.Error("Private key is nil")
|
||
return nil, errors.New("private key is nil")
|
||
}
|
||
|
||
der := priv.Bytes()
|
||
log.Debug("SM2 private key marshaled to DER successfully",
|
||
"derLength", len(der),
|
||
)
|
||
return der, nil
|
||
}
|
||
|
||
// ParseSM2PrivateDER 从DER格式解析私钥.
|
||
// 将DER格式的字节数组解析为SM2私钥对象.
|
||
func ParseSM2PrivateDER(der []byte) (crpt.PrivateKey, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Parsing SM2 private key from DER format",
|
||
"derLength", len(der),
|
||
)
|
||
if len(der) == 0 {
|
||
log.Error("DER encoded private key is empty")
|
||
return nil, errors.New("DER encoded private key cannot be empty")
|
||
}
|
||
|
||
key, err := crpt.PrivateKeyFromBytes(crpt.SM2, der)
|
||
if err != nil {
|
||
log.Error("Failed to parse SM2 private key from DER",
|
||
"error", err,
|
||
"derLength", len(der),
|
||
)
|
||
return nil, fmt.Errorf("failed to parse SM2 private key from DER (length: %d): %w", len(der), err)
|
||
}
|
||
log.Debug("SM2 private key parsed from DER successfully")
|
||
return key, nil
|
||
}
|
||
|
||
// MarshalSM2PublicDER 将公钥编码为DER格式.
|
||
// 将SM2公钥转换为DER格式的字节数组,用于存储或传输.
|
||
func MarshalSM2PublicDER(pub crpt.PublicKey) ([]byte, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Marshaling SM2 public key to DER format")
|
||
if pub == nil {
|
||
log.Error("Public key is nil")
|
||
return nil, errors.New("public key is nil")
|
||
}
|
||
|
||
der := pub.Bytes()
|
||
log.Debug("SM2 public key marshaled to DER successfully",
|
||
"derLength", len(der),
|
||
)
|
||
return der, nil
|
||
}
|
||
|
||
// ParseSM2PublicDER 从DER格式解析公钥.
|
||
// 将DER格式的字节数组解析为SM2公钥对象.
|
||
// 返回解析后的公钥,如果数据不是有效的SM2公钥则返回错误.
|
||
func ParseSM2PublicDER(der []byte) (crpt.PublicKey, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Parsing SM2 public key from DER format",
|
||
"derLength", len(der),
|
||
)
|
||
if len(der) == 0 {
|
||
log.Error("DER encoded public key is empty")
|
||
return nil, errors.New("DER encoded public key cannot be empty")
|
||
}
|
||
|
||
publicKey, err := crpt.PublicKeyFromBytes(crpt.SM2, der)
|
||
if err != nil {
|
||
log.Error("Failed to parse SM2 public key",
|
||
"error", err,
|
||
"derLength", len(der),
|
||
)
|
||
return nil, fmt.Errorf("failed to parse SM2 public key (DER length: %d): %w", len(der), err)
|
||
}
|
||
|
||
log.Debug("SM2 public key parsed from DER successfully")
|
||
return publicKey, nil
|
||
}
|
||
|
||
// SignMessage 使用密钥对签名消息(标准SM2签名).
|
||
// 使用标准SM2算法对消息进行签名,不包含用户标识(uid).
|
||
func (kp *SM2KeyPair) SignMessage(msg []byte) ([]byte, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Signing message with SM2 key pair",
|
||
"messageLength", len(msg),
|
||
)
|
||
if kp.Private == nil {
|
||
log.Error("Private key is nil")
|
||
return nil, ErrPrivateKeyIsNil
|
||
}
|
||
|
||
signature, err := crpt.SignMessage(kp.Private, msg, rand.Reader, nil)
|
||
if err != nil {
|
||
log.Error("Failed to sign message with SM2",
|
||
"error", err,
|
||
"messageLength", len(msg),
|
||
)
|
||
return nil, err
|
||
}
|
||
log.Debug("Message signed successfully with SM2",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(signature),
|
||
)
|
||
return signature, nil
|
||
}
|
||
|
||
// SignGM 使用密钥对签名消息(国密标准SM2签名,带uid).
|
||
// 使用符合GB/T 32918标准的SM2算法对消息进行签名,包含用户标识(uid).
|
||
// uid用于Z值计算,通常为用户ID或标识符.
|
||
func (kp *SM2KeyPair) SignGM(msg, uid []byte) ([]byte, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Signing message with SM2 GM standard",
|
||
"messageLength", len(msg),
|
||
"uidLength", len(uid),
|
||
)
|
||
if kp.Private == nil {
|
||
log.Error("Private key is nil")
|
||
return nil, ErrPrivateKeyIsNil
|
||
}
|
||
|
||
// go-crpt uses SM3 hash internally, pass nil for standard signing
|
||
signature, err := crpt.SignMessage(kp.Private, msg, rand.Reader, nil)
|
||
if err != nil {
|
||
log.Error("Failed to sign message with SM2 GM standard",
|
||
"error", err,
|
||
"messageLength", len(msg),
|
||
)
|
||
return nil, err
|
||
}
|
||
log.Debug("Message signed successfully with SM2 GM standard",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(signature),
|
||
)
|
||
return signature, nil
|
||
}
|
||
|
||
// VerifyMessage 使用公钥验证签名(标准SM2验签).
|
||
// 验证标准SM2签名,不使用用户标识(uid).
|
||
// 返回验证结果和可能的错误.如果验证失败但没有错误发生,返回(false, nil).
|
||
func (kp *SM2KeyPair) VerifyMessage(msg, sig []byte) (bool, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Verifying message signature with SM2",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(sig),
|
||
)
|
||
if kp.Public == nil {
|
||
log.Error("Public key is nil")
|
||
return false, ErrPublicAndKeysNotMatch
|
||
}
|
||
|
||
ok, err := crpt.VerifyMessage(kp.Public, msg, crpt.Signature(sig), nil)
|
||
if err != nil {
|
||
log.Error("Error verifying message with SM2",
|
||
"error", err,
|
||
"messageLength", len(msg),
|
||
)
|
||
return false, err
|
||
}
|
||
if ok {
|
||
log.Debug("Message signature verified successfully with SM2",
|
||
"messageLength", len(msg),
|
||
)
|
||
} else {
|
||
log.Warn("Message signature verification failed with SM2",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(sig),
|
||
)
|
||
}
|
||
return ok, nil
|
||
}
|
||
|
||
// VerifyGM 使用公钥验证签名(国密标准SM2验签,带uid).
|
||
// 验证符合GB/T 32918标准的SM2签名,使用用户标识(uid).
|
||
// 返回验证结果和可能的错误.如果验证失败但没有错误发生,返回(false, nil).
|
||
func (kp *SM2KeyPair) VerifyGM(msg, sig, uid []byte) (bool, error) {
|
||
log := logger.GetGlobalLogger()
|
||
log.Debug("Verifying message signature with SM2 GM standard",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(sig),
|
||
"uidLength", len(uid),
|
||
)
|
||
if kp.Public == nil {
|
||
log.Error("Public key is nil")
|
||
return false, ErrPublicAndKeysNotMatch
|
||
}
|
||
|
||
// go-crpt uses SM3 hash internally
|
||
ok, err := crpt.VerifyMessage(kp.Public, msg, crpt.Signature(sig), nil)
|
||
if err != nil {
|
||
log.Error("Error verifying message with SM2 GM standard",
|
||
"error", err,
|
||
"messageLength", len(msg),
|
||
)
|
||
return false, err
|
||
}
|
||
if ok {
|
||
log.Debug("Message signature verified successfully with SM2 GM standard",
|
||
"messageLength", len(msg),
|
||
)
|
||
} else {
|
||
log.Warn("Message signature verification failed with SM2 GM standard",
|
||
"messageLength", len(msg),
|
||
"signatureLength", len(sig),
|
||
)
|
||
}
|
||
return ok, nil
|
||
}
|