hi-server/pkg/signature/validator.go
shanshanzhong 7308aa9191
Some checks failed
Build docker and publish / build (20.15.1) (push) Failing after 7m37s
无订阅 支付后出现两个订阅
2026-03-05 21:53:36 -08:00

62 lines
1.2 KiB
Go

package signature
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strconv"
"time"
)
type Validator struct {
conf SignatureConf
nonceStore NonceStore
}
func NewValidator(conf SignatureConf, store NonceStore) *Validator {
return &Validator{
conf: conf,
nonceStore: store,
}
}
func (v *Validator) windowSeconds() int64 {
if v.conf.ValidWindowSeconds <= 0 {
return 300
}
return v.conf.ValidWindowSeconds
}
func (v *Validator) Validate(ctx context.Context, appId, timestamp, nonce, signature, stringToSign string) error {
secret, ok := v.conf.AppSecrets[appId]
if !ok {
return ErrSignatureMissing
}
ts, err := strconv.ParseInt(timestamp, 10, 64)
if err != nil {
return ErrSignatureExpired
}
diff := time.Now().Unix() - ts
if diff < 0 {
diff = -diff
}
if diff > v.windowSeconds() {
return ErrSignatureExpired
}
replayed, err := v.nonceStore.SetIfNotExists(ctx, appId, nonce, v.windowSeconds()+60)
if err == nil && replayed {
return ErrSignatureReplay
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(stringToSign))
expected := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(expected), []byte(signature)) {
return ErrSignatureInvalid
}
return nil
}