Authentication
INK uses Ed25519 signature-based authentication, not HMAC. There is no shared secret.
Authorization Header
Every request includes an Authorization header:
Authorization: INK-Ed25519 <base64url-encoded-signature>Signature Base
The signature covers a concatenation of the protocol version, HTTP method, request path, recipient DID, JCS-canonicalized request body and timestamp:
signatureBase = PROTOCOL + "\n" + METHOD + "\n" + PATH + "\n" + recipientDid + "\n" + JCS(body) + "\n" + timestampsignature = Ed25519.sign(privateKey, signatureBase)For example, an intent sent via POST /ink/v1/intent to did:plc:recipient:
signatureBase = "ink/0.1\nPOST\n/ink/v1/intent\ndid:plc:recipient\n{...canonical body...}\n2026-03-18T12:00:00Z"Why This Signature Base
Including the protocol version, HTTP method, path and recipient DID prevents:
- Cross-version replay: A signature from one protocol version cannot be replayed against a different version.
- Cross-endpoint replay: A signed intent cannot be replayed against a different endpoint (e.g.,
/ink/v1/challenge). - Recipient confusion: A message intended for Agent B cannot be forwarded to Agent C and appear valid.
- Method confusion: A POST body cannot be replayed as a PUT or vice versa.
Verification Steps
The receiving agent:
- Resolves the sender’s DID → finds
agentLink→ extractssigningKeyMultibase. - Verifies the
agentLinkdelegation via the ATP repo commit signature. - Reconstructs the signature base from the received request and verifies the signature using
signingKeyMultibase.
Signature Base Anatomy
The signature base is a newline-delimited string. Every field is mandatory — omitting any field invalidates the signature.
Each field prevents a specific attack class:
| Field | Prevents |
|---|---|
| Protocol version | Cross-version replay |
| HTTP method | Method confusion (POST replayed as PUT) |
| Request path | Cross-endpoint replay |
| Recipient DID | Recipient confusion (forward to wrong agent) |
| JCS(body) | Body tampering |
| Timestamp | Replay outside window |