Some checks failed
Build docker and publish / build (20.15.1) (push) Failing after 7m37s
62 lines
1.2 KiB
Go
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
|
|
}
|