Skip to content

TypeScript: @dnsid-ai/http-signatures

DNSid RFC 9421 HTTP Message Signatures profile helpers.

This package provides signing, verification, canonicalization, digest, nonce, and algorithm-mapping helpers built on @dnsid-ai/protocol contracts. It does not include DNS or HTTPS transport defaults.

Terminal window
npm install @dnsid-ai/http-signatures @dnsid-ai/protocol
import { createHttpSignaturesProfile } from '@dnsid-ai/http-signatures';
const httpSignatures = createHttpSignaturesProfile({
domain: 'agent.example',
keyProvider,
identityResolver,
});

Verification accepts { peerCert, timeoutMs, signal }. peerCert is the trusted current application peer, required for fl=mtls, including cached identities. The overall default is 30 seconds across all signature candidates, discovery, and body digest work. Standalone verification rejects signature headers over 16 KiB, more than 16 labels, more than 64 covered components per label, and bodies over 1 MiB; bodies are bounded while reading without changing their bytes. Injected identity resolvers must honor cancellation and enforce bounded I/O. fl=logchk remains caller-owned operation policy.

@dnsid-ai/sdk also re-exports this package as httpSignatures and exports HttpSignaturesProfile / createHttpSignaturesProfile directly.

DNSid profile for RFC 9421 HTTP Message Signatures.

Signs and verifies HTTP requests/responses with DNSid operational keys. The high-level entry points are createHttpSignaturesProfile / HttpSignaturesProfile, which bind a signing agent’s domain, KeyProvider, and IdentityResolver into a profile that produces and verifies Signature / Signature-Input headers.

The package also exports the low-level RFC 9421 building blocks it is made of — component identifiers, structured-field parsing/serialization, signature-base construction (buildSignatureInput), signHttpMessage, and Content-Digest (RFC 9530) helpers — for reuse by other profiles such as @dnsid-ai/web-bot-auth.

Defined in: http-signatures/src/index.ts:251

DNSid profile for RFC 9421 HTTP Message Signatures.

Signs outbound HTTP requests with the agent’s operational key (adding Signature / Signature-Input headers, plus Content-Digest when a body is present) and verifies inbound signed requests by resolving the signer’s DNSid identity from the keyid parameter.

Prefer createHttpSignaturesProfile or HttpSignaturesProfile.fromIdentityManager for construction.

new HttpSignaturesProfile(opts): HttpSignaturesProfile;

Defined in: http-signatures/src/index.ts:271

HttpSignaturesProfileOptions

HttpSignaturesProfile

ArgumentError if opts.domain is not a valid agent FQDN.

createSignedFetch(opts): FetchLike;

Defined in: http-signatures/src/index.ts:358

Wraps a fetch implementation so every request is signed before being sent.

Streaming (ReadableStream) request bodies are rejected with ArgumentError because signing requires buffering the body to compute its digest.

CreateSignedFetchOptions

FetchLike

createSignedHttpRequest(req, opts?): Promise<Request>;

Defined in: http-signatures/src/index.ts:295

Returns a copy of the request signed with the agent’s current operational key.

Covers @method, @authority, and @target-uri by default; when the request has a body, a SHA-256 Content-Digest header is added and covered as well. The keyid signature parameter is "{domain}#{kid}", created is now, and a fresh nonce is included. The input request is not mutated.

Request

Request to sign; its body (if any) is buffered to compute the digest.

HttpSigningOptions

Extra covered components, label, tag, and expiry.

Promise<Request>

ArgumentError if the signing key kid contains # or an additional component is invalid.

verifySignedHttpRequest(req, opts?): Promise<VerifiedDomain>;

Defined in: http-signatures/src/index.ts:390

Verifies an inbound signed request and returns the signer’s verified DNSid identity.

Selects signatures (optionally by tag) and accepts exactly one valid profile candidate, ignoring unrelated or invalid coexisting signatures. Candidate checks cover: required components, presence of keyid and created, freshness (created within maxAge and clock skew, expires not passed and within maxAge of created), body/content-digest consistency (a body must be covered by a matching Content-Digest), algorithm consistency between the declared alg and the resolved key, and finally the signature itself over the reconstructed signature base.

The signer’s domain is taken from the keyid ("{domain}#{kid}") and resolved via the profile’s IdentityResolver; the signing key must appear in the signer’s published JWKS.

Request

HttpVerificationOptions = {}

Promise<VerifiedDomain>

The signer’s VerifiedDomain on success.

VerificationError with VerificationCode.SignatureInvalid for missing headers, unmet requirements, stale/future timestamps, digest or signature mismatches; with VerificationCode.RecordInvalid for malformed Signature / Signature-Input headers or ambiguous label/tag selection. Identity resolution failures propagate from the IdentityResolver.

static fromIdentityManager(identityManager, httpMessageSignatures?): HttpSignaturesProfile;

Defined in: http-signatures/src/index.ts:253

Creates a profile from a SigningIdentityManager, reusing its domain, key provider, and resolver.

SigningIdentityManager

HttpSignaturesProfileConfig

HttpSignaturesProfile

Defined in: http-signatures/src/index.ts:232

Options for HttpSignaturesProfile.createSignedFetch.

fetch: FetchLike;

Defined in: http-signatures/src/index.ts:234

Underlying fetch implementation invoked with the signed request.

optional prepareRequest?: (request) => Request | Promise<Request>;

Defined in: http-signatures/src/index.ts:238

Hook to transform each request (e.g. add headers) before it is signed.

Request

Request | Promise<Request>

optional signing?:
| HttpSigningOptions
| ((request) => HttpSigningOptions | undefined);

Defined in: http-signatures/src/index.ts:236

Signing options, or a per-request callback returning them (undefined means profile defaults).


Defined in: http-signatures/src/index.ts:209

Tuning knobs for signature freshness checks during verification.

optional clockSkew?: number;

Defined in: http-signatures/src/index.ts:213

Allowed clock skew in seconds when checking created. Default: 5.

optional maxAge?: number;

Defined in: http-signatures/src/index.ts:211

Maximum age of an HTTP message signature’s created parameter in seconds. Default: 300.


Defined in: http-signatures/src/index.ts:217

Constructor options for HttpSignaturesProfile.

domain: string;

Defined in: http-signatures/src/index.ts:219

The signing agent’s FQDN; becomes the domain half of the keyid parameter ("{domain}#{kid}").

optional httpMessageSignatures?: HttpSignaturesProfileConfig;

Defined in: http-signatures/src/index.ts:225

Verification freshness tuning; defaults apply when omitted.

identityResolver: IdentityResolver;

Defined in: http-signatures/src/index.ts:223

Resolves and verifies signer domains when verifying inbound requests.

optional keyProvider?: KeyProvider;

Defined in: http-signatures/src/index.ts:221

Provides the agent’s operational signing key. Omit for a verification-only profile.


Defined in: http-signatures/src/index.ts:55

Options for signing an HTTP request with HttpSignaturesProfile.createSignedHttpRequest.

optional additionalComponents?: ComponentIdentifier[];

Defined in: http-signatures/src/index.ts:61

Covered components to sign in addition to the profile defaults (@method, @authority, @target-uri, and content-digest when a body is present). Duplicates of already-covered components are ignored.

optional expiresInSeconds?: number;

Defined in: http-signatures/src/index.ts:67

If set, adds an expires signature parameter this many seconds after created.

optional label?: string;

Defined in: http-signatures/src/index.ts:63

Signature label used as the Signature / Signature-Input dictionary key. Default: sig1.

optional tag?: string;

Defined in: http-signatures/src/index.ts:65

Optional RFC 9421 tag signature parameter identifying the application/profile.


Defined in: http-signatures/src/index.ts:71

Options for verifying an HTTP request with HttpSignaturesProfile.verifySignedHttpRequest.

optional peerCert?: TLSCertificate;

Defined in: http-signatures/src/index.ts:73

Trusted current application peer, never the JWKS endpoint certificate.

optional requiredComponents?: ComponentIdentifier[];

Defined in: http-signatures/src/index.ts:78

Covered components the signature must include, matched exactly (name and params). Default: @method, @authority, @target-uri, matched by name only.

optional requiredTag?: string;

Defined in: http-signatures/src/index.ts:80

If set, exactly one signature with this tag parameter must be present and is the one verified.

optional signal?: AbortSignal;

Defined in: protocol/src/verification-budget.ts:6

VerificationOptions.signal

optional timeoutMs?: number;

Defined in: protocol/src/verification-budget.ts:5

Overall invocation budget, including all discovery and evidence. Default: 30 seconds.

VerificationOptions.timeoutMs


Defined in: http-signatures/src/index.ts:87

Parsed or to-be-serialized RFC 9421 signature parameters: the covered components plus the parameters of one Signature-Input dictionary member.

optional alg?: string;

Defined in: http-signatures/src/index.ts:95

alg parameter (RFC 9421 algorithm identifier, e.g. ed25519).

components: ComponentIdentifier[];

Defined in: http-signatures/src/index.ts:91

Ordered covered components included in the signature base.

optional created?: number;

Defined in: http-signatures/src/index.ts:97

created parameter (Unix seconds).

optional expires?: number;

Defined in: http-signatures/src/index.ts:99

expires parameter (Unix seconds).

optional keyId?: string;

Defined in: http-signatures/src/index.ts:93

keyid parameter; the DNSid profile uses the compound "{domain}#{kid}" convention.

label: string;

Defined in: http-signatures/src/index.ts:89

Dictionary key labeling this signature in the Signature / Signature-Input headers.

optional nonce?: string;

Defined in: http-signatures/src/index.ts:104

nonce parameter. Callers can record seen nonces to implement replay detection; verification itself does not check for reuse.

optional parameters?: SignatureParameter[];

Defined in: http-signatures/src/index.ts:112

Ordered RFC 8941 signature parameters. Parsed values always populate this list, including unknown extensions. When supplied for a newly constructed value, it is the serialization source of truth; otherwise the typed fields above are serialized in profile order.

optional tag?: string;

Defined in: http-signatures/src/index.ts:106

tag parameter identifying the application/profile.

type ComponentIdentifier =
| string
| {
name: string;
params?: Record<string, string | number | boolean>;
};

Defined in: http-signatures/src/index.ts:49

An RFC 9421 covered-component identifier: either a plain component name (a derived component like "@method" or a lowercase HTTP field name like "content-digest"), or a name plus structured-field parameters (e.g. { name: '@query-param', params: { name: 'id' } } or { name: 'x-hdr', params: { req: true } }).


type FetchLike = (input, init?) => Promise<Response>;

Defined in: http-signatures/src/index.ts:229

A fetch-compatible function, e.g. the global fetch or a wrapper around it.

RequestInfo | URL

RequestInit

Promise<Response>


type HttpMessage =
| Request
| Response
| {
message: Request | Response;
request?: Request;
};

Defined in: http-signatures/src/index.ts:119

An HTTP message to sign or verify: a Request, a Response, or a Response paired with the Request it answers (needed to resolve components with the req parameter).


type SignatureParameter = readonly [string, BareItem];

Defined in: http-signatures/src/index.ts:52

An ordered RFC 8941 bare-item signature parameter retained during parsing.

const DEFAULT_CLOCK_SKEW_SECONDS: 5 = 5;

Defined in: http-signatures/src/index.ts:124

Default allowed clock skew when checking created against the current time, in seconds.


const DEFAULT_SIGNATURE_MAX_AGE_SECONDS: 300 = 300;

Defined in: http-signatures/src/index.ts:122

Default maximum accepted age of a signature’s created parameter, in seconds.


const JOSE_TO_HTTP_SIG_ALG: Readonly<Record<string, string>>;

Defined in: http-signatures/src/index.ts:131

JOSE algorithm name to RFC 9421 HTTP signature algorithm identifier mapping supported by DNSid.


const KNOWN_DERIVED_COMPONENTS: Set<string>;

Defined in: http-signatures/src/index.ts:126

RFC 9421 derived component names accepted by this package (@query-param additionally requires a name parameter).

function buildSignatureInput(msg, params): Uint8Array;

Defined in: http-signatures/src/index.ts:747

Builds the RFC 9421 signature base for a message: one "component": value line per covered component, terminated by the canonical "@signature-params" line.

HttpMessage

SignatureParams

Uint8Array

The UTF-8 encoded signature base — the payload that is signed/verified.

ArgumentError if a covered component is invalid or cannot be resolved from the message (absent header, missing request context, unavailable derived component, or a @query-param that is absent or repeated).


function constantTimeEqual(a, b): boolean;

Defined in: http-signatures/src/index.ts:197

Constant-time comparison of two Uint8Arrays. Returns true if equal.

Uint8Array

Uint8Array

boolean


function createHttpSignaturesProfile(opts): HttpSignaturesProfile;

Defined in: http-signatures/src/index.ts:583

Creates a DNSid RFC 9421 HTTP Message Signatures profile for the given agent.

HttpSignaturesProfileOptions

HttpSignaturesProfile

const httpSignatures = createHttpSignaturesProfile({
domain: 'agent.example',
keyProvider,
identityResolver,
});
// Sign an outbound request with the agent's operational key
const signed = await httpSignatures.createSignedHttpRequest(
new Request('https://api.example/things', { method: 'POST', body: '{}' }),
);
// Verify an inbound request; returns the signer's VerifiedDomain
const signer = await httpSignatures.verifySignedHttpRequest(incomingRequest);

function generateNonce(byteLength?): string;

Defined in: http-signatures/src/index.ts:157

Generates a cryptographically random base64url nonce for HTTP message signatures.

number = 32

string


function hasComponentNamed(components, name): boolean;

Defined in: http-signatures/src/index.ts:612

Checks whether a component with the given name is present, ignoring parameters.

ComponentIdentifier[]

string

boolean


function isLowercaseHttpFieldName(name): boolean;

Defined in: http-signatures/src/index.ts:152

Checks whether a string is a valid lowercase HTTP field name (RFC 9110 token).

string

boolean


function joseAlgToHttpSigAlg(joseAlg): string;

Defined in: http-signatures/src/index.ts:143

Maps a JWK/JOSE algorithm name to the corresponding RFC 9421 HTTP Message Signature algorithm identifier.

string

string

ArgumentError if the JOSE algorithm has no mapping (see JOSE_TO_HTTP_SIG_ALG).


function parseContentDigest(headerValue): object;

Defined in: http-signatures/src/index.ts:173

Parses a Content-Digest structured field header value (RFC 9530 Dictionary).

Returns the first dictionary entry as a lowercase hash algorithm name and raw digest bytes.

string

object

digest: Uint8Array;
hashAlg: string;

ArgumentError if the header is malformed or uses an algorithm other than sha-256/sha-512.


function parseKeyId(keyId): object;

Defined in: protocol/src/utils.ts:110

Parses the DNSid SDK’s cross-profile compound key ID convention: “{domain}#{kid}”.

This is an SDK/profile convention used by packages such as @dnsid-ai/jose and @dnsid-ai/http-signatures to bind a profile-level key reference to a DNSid agent FQDN plus a JWKS “kid”. It is not a DNSid protocol wire-format requirement; the protocol itself only requires JWKS keys to carry “kid” values.

Splits on the first ’#’, normalizes the domain side with normalizeFQDN(), and rejects if either side is empty or the kid side contains another ’#’.

string

object

domain: string;
kid: string;

ArgumentError if the key ID is malformed.


function parseSignature(headerValue): Map<string, Uint8Array<ArrayBufferLike>>;

Defined in: http-signatures/src/index.ts:898

Parses a Signature header (RFC 8941 Dictionary of byte sequences) into raw signature bytes keyed by label.

string

Map<string, Uint8Array<ArrayBufferLike>>

VerificationError with VerificationCode.RecordInvalid if the header is malformed, a label is duplicated, or a member is not a byte sequence.


function parseSignatureInput(headerValue): Map<string, SignatureParams>;

Defined in: http-signatures/src/index.ts:853

Parses a Signature-Input header (RFC 8941 Dictionary of Inner Lists) into per-label signature params, preserving component and parameter order for canonical signature-base reconstruction.

string

Map<string, SignatureParams>

VerificationError with VerificationCode.RecordInvalid if the header is malformed, a label is duplicated, or a parameter has the wrong structured-field type.


function sameComponent(a, b): boolean;

Defined in: http-signatures/src/index.ts:602

Checks whether two component identifiers are equivalent: same name and identical parameters.

ComponentIdentifier

ComponentIdentifier

boolean


function serializeComponentIdentifier(component): string;

Defined in: http-signatures/src/index.ts:724

Serializes a component identifier as it appears in the signature base and Signature-Input header (quoted name plus parameters).

ComponentIdentifier

string


function serializeStructuredFieldValue(value): string;

Defined in: http-signatures/src/index.ts:719

Serializes a bare value as an RFC 8941 structured field Item (bytes become :base64: byte sequences).

| string | number | boolean | ArrayBuffer | Uint8Array<ArrayBufferLike>

string


function setDictionaryMember(
headers,
name,
label,
value
): void;

Defined in: http-signatures/src/index.ts:959

Sets one member of a structured-field Dictionary header (e.g. Signature, Signature-Input) to label=value, replacing any existing member with that label and preserving the rest.

Headers

string

string

string

void


function signHttpMessage<T>(
msg,
params,
keyProvider
): Promise<T>;

Defined in: http-signatures/src/index.ts:772

Signs an HTTP message per RFC 9421 with the key provider’s current operational key.

Builds the signature base for params.components, signs it via keyProvider.sign(), and returns a copy of the message with the params.label member set (or replaced) in its Signature-Input and Signature dictionary headers. Existing members under other labels are preserved. The input message is not mutated. Callers are responsible for setting Content-Digest before covering content-digest.

T extends Request | Response

| T | { message: T; request?: Request; }

Request or Response to sign; pass { message, request } to sign a response whose covered components reference the originating request (req parameter).

SignatureParams

Covered components and signature parameters to serialize into Signature-Input.

KeyProvider

Promise<T>

A new message of the same type carrying the signature headers.

ArgumentError if a covered component cannot be resolved (see buildSignatureInput).


function validateComponentIdentifier(component): void;

Defined in: http-signatures/src/index.ts:623

Validates a component identifier: the name must be a known derived component (KNOWN_DERIVED_COMPONENTS) or a lowercase HTTP field name, and @query-param must carry a name parameter.

ComponentIdentifier

void

ArgumentError if the component is not valid.