chore: establish local platform baseline
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
package voiceprovider
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderCallbackTimestamp = "X-Provider-Timestamp"
|
||||
HeaderCallbackSignature = "X-Provider-Signature"
|
||||
)
|
||||
|
||||
var ErrInvalidCallbackSignature = errors.New("invalid provider callback signature")
|
||||
|
||||
func SignCallback(secret []byte, timestamp string, body []byte) string {
|
||||
digest := sha256.Sum256(body)
|
||||
canonical := timestamp + "\n" + hex.EncodeToString(digest[:])
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
_, _ = mac.Write([]byte(canonical))
|
||||
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
|
||||
}
|
||||
|
||||
func VerifyCallback(secret []byte, timestamp, signature string, body []byte, now time.Time, maxSkew time.Duration) error {
|
||||
if len(secret) < 32 || strings.TrimSpace(timestamp) == "" || strings.TrimSpace(signature) == "" || maxSkew <= 0 {
|
||||
return ErrInvalidCallbackSignature
|
||||
}
|
||||
parsed, err := time.Parse(time.RFC3339, timestamp)
|
||||
if err != nil || absoluteDuration(now.Sub(parsed)) > maxSkew {
|
||||
return ErrInvalidCallbackSignature
|
||||
}
|
||||
provided, err := base64.RawURLEncoding.DecodeString(signature)
|
||||
if err != nil {
|
||||
return ErrInvalidCallbackSignature
|
||||
}
|
||||
expected, _ := base64.RawURLEncoding.DecodeString(SignCallback(secret, timestamp, body))
|
||||
if !hmac.Equal(provided, expected) {
|
||||
return ErrInvalidCallbackSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func absoluteDuration(value time.Duration) time.Duration {
|
||||
if value < 0 {
|
||||
return -value
|
||||
}
|
||||
return value
|
||||
}
|
||||
Reference in New Issue
Block a user