Documentation Index Fetch the complete documentation index at: https://mintlify.com/PaymanAI/sigilum/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Sigilum implements HTTP message signatures based on RFC 9421 with a specific profile for AI agent authentication. All signed requests use Ed25519 signatures and include required Sigilum headers for identity verification.
Profile name : sigilum-rfc9421-v1
Signature algorithm : Ed25519
Test vectors : sdks/test-vectors/http-signatures-rfc9421.json
Every signed request includes two RFC 9421 headers:
Defines the signature parameters and components:
Signature-Input : sig1=("@method" "@target-uri" "content-digest"
"sigilum-namespace" "sigilum-subject" "sigilum-agent-key"
"sigilum-agent-cert");created=1700000000;nonce="123e4567-e89b-12d3-a456-426614174000";alg="ed25519";keyid="did:sigilum:alice#ed25519-99fb00dc16ee555a"
Parameters:
created : Unix timestamp when signature was created
nonce : Unique nonce for replay protection (UUID format)
alg : Signature algorithm (ed25519 only)
keyid : DID URL identifying the signing key
Signature
Contains the base64-encoded signature:
Signature : sig1=:vGp+WLmSr0BWNci2lBhcJORg39ot+3Uu1aaVG2wGEKLItK/964hFaRrVd7DHf/2e3ykGpIacoM9Q5gs/tPy6Dw==:
Signed Components
The signature covers specific HTTP message components. The exact set depends on whether the request includes a body.
Without Body (GET, DELETE)
Required components:
@method - HTTP method (lowercase)
@target-uri - Full request URI (fragments stripped)
sigilum-namespace - Owner namespace
sigilum-subject - Requester principal
sigilum-agent-key - Agent public key
sigilum-agent-cert - Agent certificate
With Body (POST, PUT, PATCH)
Required components:
@method - HTTP method (lowercase)
@target-uri - Full request URI (fragments stripped)
content-digest - SHA-256 hash of request body
sigilum-namespace - Owner namespace
sigilum-subject - Requester principal
sigilum-agent-key - Agent public key
sigilum-agent-cert - Agent certificate
Component Details
@method (Derived Component)
HTTP method in lowercase:
"@method": get
"@method": post
"@method": put
"@method": delete
Canonicalization : Always lowercase, regardless of how the request was sent.
@target-uri (Derived Component)
Full request URI with fragments stripped:
Original URL: https://api.sigilum.local/v1/namespaces/alice/claims?status=approved#fragment
Canonical: https://api.sigilum.local/v1/namespaces/alice/claims?status=approved
Fragment stripping : URL fragments (#fragment) are removed before signing.
Port handling : Non-standard ports are preserved:
https://api.sigilum.local:8443/v1/records/alpha?view=full
Query encoding : URL-encoded query parameters are preserved as-is:
https://api.sigilum.local/v1/audit/events?cursor=abc%2F123&limit=50
SHA-256 hash of the request body in RFC 9530 format:
Content-Digest : sha-256=:5toCTO6LRikiTvJ0Ha+F6ucUxaTs3wMsnaImDBR0NZg=:
Computation:
Take the raw request body bytes
Compute SHA-256 hash
Encode in base64
Wrap in RFC 9530 format: sha-256=:base64hash:
Example body:
Expected digest:
sha-256=:5toCTO6LRikiTvJ0Ha+F6ucUxaTs3wMsnaImDBR0NZg=:
Requirement : MUST be present when request has a body, MUST be omitted when no body.
The owner namespace:
Validation : Must match the namespace in the agent certificate and DID.
The requester principal identifier:
Sigilum-Subject : customer-12345
Purpose : Stable requester principal ID within the namespace. Services can apply subject-aware policies (e.g., MCP tool filtering).
Default behavior : When omitted at signing time, SDKs default to the signer namespace.
Responsibility : Platforms must set this accurately to reflect “who triggered this action” (authenticated human or system identity).
The agent’s public key:
Sigilum-Agent-Key : ed25519:J07dj/co4diCmQYTTQGq4adhnMKYejHazCYUQ7eBh0k=
Format : ed25519:<base64-encoded-public-key>
Validation : Must match the public key in the certificate and be authorized for the namespace.
The agent’s certificate (JSON, base64-encoded):
Sigilum-Agent-Cert : eyJ2ZXJzaW9uIjoxLCJuYW1lc3BhY2UiOiJmaXh0dXJlLWFsaWNlIiwiZGlkIjoiZGlkOnNpZ2lsdW06Zml4dHVyZS1hbGljZSIsImtleUlkIjoiZGlkOnNpZ2lsdW06Zml4dHVyZS1hbGljZSNlZDI1NTE5LTk5ZmIwMGRjMTZlZTU1NWEiLCJwdWJsaWNLZXkiOiJlZDI1NTE5OkowN2RqL2NvNGRpQ21RWVRUUUdxNGFkaG5NS1llakhhekhZVVE3ZUJoMGs9IiwiaXNzdWVkQXQiOiIyMDI2LTAyLTIwVDE4OjA0OjI2WiIsImV4cGlyZXNBdCI6bnVsbCwicHJvb2YiOnsiYWxnIjoiZWQyNTUxOSIsInNpZyI6InZHcC1XTG1TcjBCV05jaTJsQmhjSk9SZzM5b3QtM1V1MWFhVkcyd0dFS0xJdEtfOTY0aEZhUnJWZDdESGZfMmUzeWtHcElhY29NOVE1Z3NfdFB5NkR3In0sImlzc3VlZEJ5Ijoic2lnaWx1bS5sb2NhbC1maXh0dXJlIn0=
Format : Base64-encoded JSON certificate object
Certificate structure (decoded):
{
"version" : 1 ,
"namespace" : "fixture-alice" ,
"did" : "did:sigilum:fixture-alice" ,
"keyId" : "did:sigilum:fixture-alice#ed25519-99fb00dc16ee555a" ,
"publicKey" : "ed25519:J07dj/co4diCmQYTTQGq4adhnMKYejHazCYUQ7eBh0k=" ,
"issuedAt" : "2026-02-20T18:04:26Z" ,
"expiresAt" : null ,
"proof" : {
"alg" : "ed25519" ,
"sig" : "vGp-WLmSr0BWNci2lBhcJORg39ot-3Uu1aaVG2wGEKLItK_964hFaRrVd7DHf_2e3ykGpIacoM9Q5gs_tPy6Dw"
},
"issuedBy" : "sigilum.local-fixture"
}
The certificate includes a self-signature over a canonical text representation.
Canonical Certificate Text
Certificate proof signs UTF-8 text with newline-separated fields:
sigilum-certificate-v1
namespace:<namespace>
did:<did>
key-id:<keyId>
public-key:<publicKey>
issued-at:<issuedAt>
expires-at:<expiresAt-or-empty>
Example:
sigilum-certificate-v1
namespace:fixture-alice
did:did:sigilum:fixture-alice
key-id:did:sigilum:fixture-alice#ed25519-99fb00dc16ee555a
public-key:ed25519:J07dj/co4diCmQYTTQGq4adhnMKYejHazCYUQ7eBh0k=
issued-at:2026-02-20T18:04:26Z
expires-at:
Field ordering : Fields MUST appear in this exact order.
Empty expiration : When expiresAt is null, the line ends after the colon.
Signature Verification
Verifiers MUST validate:
Signature headers present : Signature-Input and Signature headers exist
Headers parseable : Headers conform to RFC 9421 syntax
Certificate valid : Agent certificate is valid and not expired
Namespace consistency : Namespace matches across headers, certificate, and DID
Key consistency : Public key matches between sigilum-agent-key and certificate
KeyID consistency : keyid parameter matches certificate keyId
Content digest : If body exists, content-digest matches computed hash
Signature correctness : Ed25519 signature verifies against the canonical signature base
Timestamp freshness : created timestamp is recent (implementation-defined window)
Nonce uniqueness : Nonce has not been seen before (replay protection)
Stable error codes : SDKs expose machine-readable codes on verification failure:
SIG_CONTENT_DIGEST_MISMATCH - Content digest doesn’t match body
SIG_INVALID_SIGNATURE - Ed25519 signature verification failed
SIG_EXPIRED - Signature timestamp too old
SIG_NONCE_REPLAY - Nonce already used
SIG_NAMESPACE_MISMATCH - Namespace inconsistency
SIG_KEY_MISMATCH - Key inconsistency
Test Vectors
Shared conformance vectors in sdks/test-vectors/http-signatures-rfc9421.json include:
Positive Vectors
GET request without body:
{
"name" : "get-no-body-fragment" ,
"method" : "GET" ,
"url" : "https://api.sigilum.local/v1/namespaces/alice/claims?status=approved#fragment" ,
"body" : null ,
"expected_target_uri" : "https://api.sigilum.local/v1/namespaces/alice/claims?status=approved" ,
"expected_method_component" : "get" ,
"expected_components" : [
"@method" ,
"@target-uri" ,
"sigilum-namespace" ,
"sigilum-subject" ,
"sigilum-agent-key" ,
"sigilum-agent-cert"
]
}
POST request with body:
{
"name" : "post-with-body" ,
"method" : "POST" ,
"url" : "https://api.sigilum.local/v1/namespaces/alice/claims" ,
"body" : "{ \" action \" : \" approve \" }" ,
"expected_target_uri" : "https://api.sigilum.local/v1/namespaces/alice/claims" ,
"expected_method_component" : "post" ,
"expected_content_digest" : "sha-256=:5toCTO6LRikiTvJ0Ha+F6ucUxaTs3wMsnaImDBR0NZg=:" ,
"expected_components" : [
"@method" ,
"@target-uri" ,
"content-digest" ,
"sigilum-namespace" ,
"sigilum-subject" ,
"sigilum-agent-key" ,
"sigilum-agent-cert"
]
}
PUT request with query and port:
{
"name" : "put-with-body-query-and-port" ,
"method" : "PUT" ,
"url" : "https://api.sigilum.local:8443/v1/records/alpha?view=full#section" ,
"body" : "{ \" text \" : \" hello world \" , \" count \" :42}" ,
"expected_target_uri" : "https://api.sigilum.local:8443/v1/records/alpha?view=full" ,
"expected_method_component" : "put" ,
"expected_content_digest" : "sha-256=:Xruw00DsBxReBcikx32MJ+Rs/9hMiEJ6/vjfZhtV2Mc=:"
}
DELETE with encoded query:
{
"name" : "delete-no-body-encoded-query" ,
"method" : "DELETE" ,
"url" : "https://api.sigilum.local/v1/audit/events?cursor=abc%2F123&limit=50#ignored" ,
"body" : null ,
"expected_target_uri" : "https://api.sigilum.local/v1/audit/events?cursor=abc%2F123&limit=50" ,
"expected_method_component" : "delete"
}
Negative Vectors (Tamper Detection)
Tampered method:
{
"name" : "tampered-method" ,
"source_vector" : "get-no-body-fragment" ,
"mutation" : "method" ,
"value" : "POST" ,
"expected_reason_contains" : "signature"
}
Tampered namespace header:
{
"name" : "tampered-namespace-header" ,
"source_vector" : "get-no-body-fragment" ,
"mutation" : "header" ,
"field" : "sigilum-namespace" ,
"value" : "mallory" ,
"expected_reason_contains" : "namespace"
}
Tampered body (content-digest mismatch):
{
"name" : "tampered-body-content-digest" ,
"source_vector" : "post-with-body" ,
"mutation" : "body" ,
"value" : "{ \" action \" : \" deny \" }" ,
"expected_reason_contains" : "content-digest"
}
Fixed Test Values
Test vectors use fixed values for reproducibility:
{
"created" : 1700000000 ,
"nonce" : "123e4567-e89b-12d3-a456-426614174000"
}
Production behavior : In production, SDKs rotate these values:
created: Current Unix timestamp
nonce: Fresh UUID v4 for each request
SDK Implementation Requirements
All SDKs MUST:
Generate signatures conforming to this profile
Strip URL fragments before signing @target-uri
Lowercase HTTP methods in @method component
Include content-digest when request has a body
Omit content-digest when request has no body
Verify all required components when validating signatures
Check certificate proof signature
Enforce namespace/key consistency across headers
Provide stable error codes for verification failures
Pass conformance tests using shared test vectors
Example Complete Request
Request:
POST /v1/namespaces/alice/claims HTTP / 1.1
Host : api.sigilum.local
Content-Type : application/json
Content-Digest : sha-256=:5toCTO6LRikiTvJ0Ha+F6ucUxaTs3wMsnaImDBR0NZg=:
Sigilum-Namespace : alice
Sigilum-Subject : customer-12345
Sigilum-Agent-Key : ed25519:J07dj/co4diCmQYTTQGq4adhnMKYejHazCYUQ7eBh0k=
Sigilum-Agent-Cert : eyJ2ZXJzaW9uIjoxLC4uLn0=
Signature-Input : sig1=("@method" "@target-uri" "content-digest" "sigilum-namespace" "sigilum-subject" "sigilum-agent-key" "sigilum-agent-cert");created=1700000000;nonce="123e4567-e89b-12d3-a456-426614174000";alg="ed25519";keyid="did:sigilum:alice#ed25519-99fb00dc16ee555a"
Signature : sig1=:vGp+WLmSr0BWNci2lBhcJORg39ot+3Uu1aaVG2wGEKLItK/964hFaRrVd7DHf/2e3ykGpIacoM9Q5gs/tPy6Dw==:
{ "action" : "approve" }
Protocol Overview High-level protocol documentation
Security Security considerations and best practices
TypeScript SDK Implementation in TypeScript
Test Vectors Complete test vector suite