Skip to content

signatures

Signed requests and responses between a runner and the platform.

Every request a runner sends, and every response the platform returns, carries an HTTP Message Signature (RFC 9421) made with Ed25519 and a Content-Digest of its body (RFC 9530). The covered components are fixed:

  • a request covers its method, path, query and body digest;
  • a response covers its status and body digest, and the method, path, query, body digest and signature of the request it answers. The request's signature carries its nonce, so a response answers exactly one request and cannot be replayed as the answer to another, even an identical one.

The signature's created time must lie within MAX_SKEW_SECONDS of the verifier's clock, and every signature carries a random nonce. Ed25519 is deterministic, so without the nonce two identical requests in one second would carry identical signatures. A verifier that remembers the signatures it has seen for that long refuses a replayed message.

Verification is strict: a message whose Signature-Input is not exactly the one this module would write, for the expected components, is refused. Only this protocol's two parties speak it, so there is nothing to negotiate.

ParsedSignature dataclass

A message's signature, read but not yet verified.

RequestParts dataclass

What a signature covers of a request.

ResponseParts dataclass

What a signature covers of a response.

SignatureError

Bases: Exception

A message's signature or digest does not hold.

content_digest(body)

Return the Content-Digest field value for a body (SHA-256).

new_nonce()

Return a random nonce for one signature.

parse_signature(headers)

Read a message's signature without verifying it.

The caller looks up the key named by keyid and passes it to :func:verify_request or :func:verify_response. Anything malformed raises SignatureError, never another exception.

sign_request(key, keyid, request, created)

Return the headers that sign a request.

sign_response(key, keyid, response, request, request_signature, created)

Return the headers that sign a response to request, signed with request_signature.

signature_base(covered, params)

Return the signature base for covered components and their values.

covered holds each component identifier as it is serialised (for example '"@method"' or '"@path";req') with its value.

signature_params(components, created, keyid, nonce=None)

Return the @signature-params value for covered components.

verify_request(parsed, headers, request, public_key, now)

Verify a request's digest and signature, or raise SignatureError.

verify_response(parsed, headers, response, request, request_signature, public_key, now)

Verify a response to a request signed with request_signature, or raise SignatureError.