diff --git a/README.md b/README.md index 605d68c..7e8afe5 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,59 @@ valid at time of fetch. # Source Hosts Source hosts may be whitelisted in the pixa configuration. If not in the -explicit whitelist, a signature using a shared secret must be appended. It -is constructed using HMAC in the following way: +explicit whitelist, a signature using a shared secret must be appended. -FIXME +## Signature Specification + +Signatures use HMAC-SHA256 and include an expiration timestamp to prevent replay attacks. + +### Signed Data Format + +The signature is computed over a colon-separated string: + +``` +HMAC-SHA256(secret, "host:path:query:width:height:format:expiration") +``` + +Where: +- `host` - Source origin hostname (e.g., `cdn.example.com`) +- `path` - Source path (e.g., `/photos/cat.jpg`) +- `query` - Source query string, empty string if none +- `width` - Requested width in pixels, `0` for original +- `height` - Requested height in pixels, `0` for original +- `format` - Output format (jpeg, png, webp, avif, gif, orig) +- `expiration` - Unix timestamp when signature expires + +### URL Format with Signature + +``` +/v1/image///.?sig=&exp= +``` + +### Example + +For a request to resize `https://cdn.example.com/photos/cat.jpg` to 800x600 WebP +with expiration at Unix timestamp 1704067200: + +1. Build the signature input: + ``` + cdn.example.com:/photos/cat.jpg::800:600:webp:1704067200 + ``` + +2. Compute HMAC-SHA256 with your secret key + +3. Base64URL-encode the result + +4. Final URL: + ``` + /v1/image/cdn.example.com/photos/cat.jpg/800x600.webp?sig=&exp=1704067200 + ``` + +### Whitelist Patterns + +The whitelist supports two pattern types: +- **Exact match**: `cdn.example.com` - matches only that host +- **Suffix match**: `.example.com` - matches `cdn.example.com`, `images.example.com`, and `example.com` # configuration