docs/examples/webhook-receivers/rust-axum/src/main.rs
Cargo.toml
src/main.rs
Run
axum-server with rustls for direct TLS.
Why verify_strict
verify_strict enforces RFC-8032 strict-mode rules:
- Rejects malleable signatures (signatures whose
svalue is not in canonical form) - Rejects public keys with point-at-infinity edge cases
verify you’d accept some
technically-valid Ed25519 signatures that the original spec rejects — a defense-in-depth
issue, not a correctness one for our payloads.
Body extraction order
axum’sBytes extractor reads the raw body before any deserialization. Do not put
a Json<T> extractor before Bytes — that would consume the body and you’d sign
over an empty input.
If you need typed access to the body, parse after verification:
Idempotency
The reference receiver above does NOT enforce idempotency. For production, persistalert_id in your DB or Redis with a 24h TTL:
Deploy
For a hobby endpoint:- Run as a systemd unit
- Set
PEGANA_PUB_KEY_B64from a secret store - Front with TLS + rate-limiting reverse proxy
- Ship
tracingto your log aggregator
Why ed25519-dalek
- Pure Rust, no system OpenSSL dependency
- Audited
- Constant-time by construction
- Available in
no_stdmode for embedded use
ring —
same algorithm, different crate.
Next
TypeScript example
Web Crypto API for edge runtimes.
Python example
FastAPI + cryptography.