A Go implementation of the Standard Webhooks specification. This package provides a secure, reliable, and standard way to sign and verify webhook payloads, making it easier for providers to send and consumers to receive webhooks.
- Full compliance with the Standard Webhooks specification
- Multiple signature algorithms support:
- ED25519 (asymmetric,
v1a
) - HMAC-SHA256 (symmetric,
v1
)
- ED25519 (asymmetric,
- Multiple simultaneous signers and verifiers for graceful algorithm transitions
- Protection against replay attacks with timestamp validation
- Extensible interface for custom signing methods
- Thread-safe implementation
- Comprehensive test coverage
go get github.com/krofort/std-webhooks-go
import "github.com/krofort/std-webhooks-go"
// Create a signer and verifier with HMAC
key := []byte("your-secret-key")
signer := webhooks.NewWebhookSigner(webhooks.NewHMACSigner(key))
verifier := webhooks.NewWebhookVerifier(webhooks.NewHMACSigner(key))
// Sign a payload
signature, err := signer.Sign("message-id", time.Now(), []byte("your-payload"))
if err != nil {
log.Fatal(err)
}
// Verify a payload
headers := http.Header{}
headers.Set(webhooks.HeaderWebhookID, "message-id")
headers.Set(webhooks.HeaderWebhookSignature, signature)
headers.Set(webhooks.HeaderWebhookTimestamp, strconv.FormatInt(time.Now().Unix(), 10))
err = verifier.Verify([]byte("your-payload"), headers)
if err != nil {
log.Fatal(err)
}
// Generate or load your ED25519 keys
publicKey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
// Create signer and verifier
signer := webhooks.NewWebhookSigner(webhooks.NewED25519Signer(privateKey))
verifier := webhooks.NewWebhookVerifier(webhooks.NewED25519Verifier(publicKey))
// Create signers with both ED25519 and HMAC
signer := webhooks.NewWebhookSigner(
webhooks.NewED25519Signer(privateKey),
webhooks.NewHMACSigner(hmacKey),
)
// Create verifier with both ED25519 and HMAC
verifier := webhooks.NewWebhookVerifier(
webhooks.NewED25519Verifier(publicKey),
webhooks.NewHMACSigner(hmacKey),
)
// Or add them dynamically
signer.AddSigner(webhooks.NewHMACSigner(anotherKey))
verifier.AddVerifier(webhooks.NewHMACSigner(anotherKey))
This implementation follows the Standard Webhooks specification for:
The package uses the standard webhook headers:
webhook-id
: A unique identifier for the webhook messagewebhook-signature
: The signature(s) of the payloadwebhook-timestamp
: Unix timestamp of when the webhook was sent
The signature format follows the standard:
<version>,<base64-signature>
When using multiple signers, signatures are space-separated:
v1a,<base64-ed25519-sig> v1,<base64-hmac-sig>
- Replay Attack Prevention: Includes timestamp validation with a 5-minute tolerance
- Multiple Signatures: Supports multiple signing algorithms for security and flexibility
- Standard Cryptography: Uses well-tested Go crypto packages
- Non-repudiation: Supports ED25519 for cryptographic proof of origin
- HMAC Support: Provides symmetric key verification option
You can implement custom signing methods by implementing the Signer
and/or Verifier
interfaces:
type Signer interface {
Version() string
Sign(message []byte) ([]byte, error)
}
type Verifier interface {
Version() string
Verify(message, signature []byte) error
}
The package provides standard error types:
ErrRequiredHeaders
: Missing required headersErrInvalidHeaders
: Invalid header formatErrNoMatchingSignature
: No valid signature foundErrMessageTooOld
: Message timestamp is too oldErrMessageTooNew
: Message timestamp is in the futureErrNoSigners
: No signers configuredErrNoVerifiers
: No verifiers configured
-
Algorithm Choice:
- Use ED25519 for production environments where non-repudiation is important
- Use HMAC for simpler implementations or when sharing public keys is impractical
-
Key Management:
- Rotate keys periodically
- Use environment variables or secure key management systems
- Never hardcode secret keys
-
Signature Verification:
- Always verify timestamps to prevent replay attacks
- Implement proper error handling for all verification steps
- Consider using multiple signature methods during algorithm transitions
Contributions are welcome! Please feel free to submit a Pull Request. Make sure to read the Standard Webhooks Specification before contributing.
This project is licensed under the MIT License - see the LICENSE file for details.