Documentation
¶
Overview ¶
Package signature provides low-level helpers for optional signed ACP request headers.
HMACVerifier verifies a base64url HMAC-SHA256 signature over an RFC 3339 timestamp and canonical JSON body. Merchant-Signature on order webhooks uses a different wire format; use github.com/sumup/acp/acpwebhook to send those events.
Index ¶
- func AbsDuration(d time.Duration) time.Duration
- func BuildSigningPayload(ts time.Time, canonicalBody []byte) []byte
- func CanonicalizeJSONBody(raw []byte) ([]byte, error)
- func ParseTimestamp(value string) (time.Time, error)
- func ReadAndBufferBody(r *http.Request) ([]byte, error)
- type HMACVerifier
- type Material
- type Verifier
- type VerifierFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AbsDuration ¶
AbsDuration returns the absolute value of the supplied duration.
func BuildSigningPayload ¶
BuildSigningPayload constructs the canonical string that is HMAC-signed.
func CanonicalizeJSONBody ¶
CanonicalizeJSONBody normalizes arbitrary JSON into canonical form for signing.
func ParseTimestamp ¶
ParseTimestamp accepts Timestamp header values in RFC3339 or RFC3339Nano format.
Types ¶
type HMACVerifier ¶
type HMACVerifier struct {
Key []byte
}
HMACVerifier validates signatures that were produced by taking the base64url-encoded HMAC-SHA256 of `RFC3339(timestamp) + "." + canonicalJSON`.
Example ¶
package main
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"time"
"github.com/sumup/acp/signature"
)
func main() {
key := []byte("request-signing-secret")
timestamp := time.Date(2026, 4, 17, 10, 30, 0, 0, time.UTC)
body, err := signature.CanonicalizeJSONBody([]byte(`{"currency":"usd","line_items":[]}`))
if err != nil {
panic(err)
}
mac := hmac.New(sha256.New, key)
_, _ = mac.Write(signature.BuildSigningPayload(timestamp, body))
encoded := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
err = (signature.HMACVerifier{Key: key}).Verify(context.Background(), signature.Material{
Signature: encoded,
Timestamp: timestamp,
CanonicalBody: body,
})
fmt.Println(err)
}
Output: <nil>
type Material ¶
type Material struct {
Signature string
Timestamp time.Time
CanonicalBody []byte
Method string
Path string
RawQuery string
Headers http.Header
}
Material captures the inputs needed to validate a signed request.