2026-08-28 · 7 min read · Rahul Chitturi
- url
- security
- debugging
A signed URL can carry the right values and still fail verification when the signer and verifier build different canonical strings. Query ordering, percent-encoding, duplicate parameters, path normalization, and timestamp formatting all affect the bytes covered by a signature.
Changing the secret rarely fixes this class of failure. It often makes diagnosis harder by adding key rotation to an encoding bug.
Capture each canonicalization stage
Use a synthetic failing URL and record the raw path, parsed parameters, canonical query, string to sign, and final signature on both sides. Compare representations before hashing rather than comparing only the digest.
- Check whether spaces become %20 or plus signs
- Confirm hex escapes use the required casing and encoding set
- Preserve duplicate keys according to the protocol's sorting rule
- Verify whether the path is normalized before or after signing
Treat parsing as a security boundary
Generic URL helpers may decode and re-encode values using rules that differ from the signature specification. Build the canonical form from a documented algorithm and reject ambiguous input instead of accepting whichever interpretation verifies.
Validate expiry and not-before fields only after the signature matches. Use a narrow clock tolerance and log the failed stage without recording sensitive query values.
A Flashman workflow
Use the URL encoder to inspect individual components, the hash tool with non-secret fixtures, the diff tool for canonical strings, and the timestamp converter for signed expiry values.
Keep protocol test vectors containing Unicode, spaces, empty values, duplicate keys, and reserved characters. Those vectors make library upgrades safer than relying on one ordinary ASCII URL.