Before you sign: three things must be true
Without 1 the signature cannot be verified (unknown key). Without 2 you are
admitted but hold no spending authority, so anything on the money path is
refused. Without 3 the signature is bound to the wrong domain and is refused.
What to sign
Send two headers,Signature-Input and Signature, plus Content-Digest when
there is a body.
Parameters:
The signature base is built per RFC 9421 §2.5: one
"<component>": <value>
line per covered component, then "@signature-params": <everything after sig1=>, joined with \n. Sign that string:
ed25519— pure EdDSA over the bytes, no prehash. Signature is the raw 64 bytes.ecdsa-p256-sha256— SHA-256, signature in rawr||sform (64 bytes), not DER.rsa-pss-sha256— SHA-256, PSS padding, salt length = 32.
Signature as sig1=:<base64>:.
Alyte compares the signed
Content-Digest with SHA-256 of the exact received
body bytes. For a request with a body, supply one canonical
sha-256=:<base64>: value and include content-digest in the covered components.
A missing, unsigned, malformed or mismatched digest fails verification. Multiple
digest values and other algorithms are not accepted by this profile.Hash and send the same bytes. Reformatting JSON, changing whitespace or changing
UTF-8 encoding after signing invalidates the request, even when its parsed JSON
would be equivalent. The conformance tool hashes and sends the same body file.
Body-size limits still apply.Prove it with the conformance tool
The tool signs exactly the way Alyte verifies — it builds the signature base with the server’s own code — so it is the reference implementation. It ships in the Alyte repository asscripts/tap-sign-request.mjs.
1 · Make a key. The private half stays with you; the public half is what
the merchant enrols.
--send it prints the three headers for you to attach in your own
client. With --send it performs the request and prints the status and body.
Exit 0 means admitted and answered 2xx; 2 means Alyte refused, and the
output says why.
Diagnosing a refusal
Signature authentication refusals use401 with the standard error envelope.
Branch on code; the message identifies some checks, while cryptographic and
body-digest failures share the generic verification failure. Payload validation,
body-size limits and purchase checks can return other statuses.
Admitted but refused on a purchase? That is the mandate, not the signature — see
the agent buy path and Errors. A buyer
has to bring your agent and grant it a cap before it can spend.

