HTTP Transport for BRC-103 Mutual Authentication
A peer-to-peer handshake still has to travel over ordinary web requests to work with existing infrastructure. This says exactly which endpoints and headers carry it.
Summary
- Why
- BRC-103 specifies a mutual authentication handshake but leaves open how those messages travel over a real network, so implementations could not interoperate over HTTP.
- What
- BRC-104 is a specification that maps BRC-103's mutual authentication and certificate exchange messages onto HTTP requests, responses, and headers.
- How
- Handshake and certificate messages are posted as JSON to a fixed `/.well-known/auth` endpoint, while ordinary API calls carry the same authentication data in `x-bsv-auth-*` headers plus an encoded payload, with a defined set of headers included in the signed preimage.
What this lets you do
- Send BRC-103 handshake and certificate messages as JSON to a fixed endpoint
- Authenticate ordinary HTTP requests without changing their basic shape
- Sign a well-defined subset of headers plus method, path, query and body
- Correlate request and response pairs using a client-generated request ID
- Return 401 or 400 responses when a handshake or signature check fails
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
Reference for an AI
Everything an assistant needs to answer questions about BRC-104 accurately, including what it depends on.
The specification
1. Abstract
This specification defines how to transport BRC-103 [1] mutual authentication messages via HTTP. It introduces:
- A
.well-known/authendpoint for non-general BRC-103 messages (e.g. handshake, certificate requests). - A mechanism for embedding “general” messages in normal HTTP requests/responses using custom
x-bsv-authheaders and an encoded request/response “payload.” - Clear rules for which HTTP headers are included in the signature and which are excluded, ensuring consistent signing and verification on both client and server.
- An approach for referencing the remote peer’s identity key and session parameters in standard HTTP requests/responses.
By adopting this scheme, implementers can re-use BRC-103’s cryptographic handshake and selective certificate exchange logic in a typical browser–server or server–server HTTP environment.
2. Introduction
BRC-103 [1] defines a peer-to-peer mutual authentication flow but leaves the transport unspecified. This document describes an HTTP layering for that flow. It details:
- Endpoints and message paths for BRC-103 handshake messages.
- A scheme for “general” messages that carry an entire HTTP request/response inside a single BRC-103 message.
- Custom HTTP headers that store BRC-103 parameters (nonces, signatures, identity keys, requested certificates, etc.).
- Mechanisms to handle typical web scenarios such as 402 Payment Required or other status codes.
Where BRC-103 gives a general outline (initialRequest, initialResponse, general, certificateRequest, certificateResponse), BRC-104 explains how those messages appear as HTTP requests and HTTP responses.
3. Relationship to BRC-103
- Mandatory Prerequisite: Implementers MUST implement or rely on BRC-103’s handshake, message types, and signature logic.
- This specification extends BRC-103 by mapping each BRC-103 message type onto HTTP requests and responses, describing /.well-known/auth usage, specialized headers (
x-bsv-auth-*), and the structured “payload” approach for general messages.
Whenever conflicts arise, BRC-103 is authoritative on handshake semantics and certificate exchange. BRC-104 only clarifies how to wrap those messages in HTTP.
4. Terminology & Definitions
- BRC-103 Message: One of
initialRequest,initialResponse,certificateRequest,certificateResponse, orgeneral. - Non-General Message: A BRC-103 message of type
initialRequest,initialResponse,certificateRequest, orcertificateResponse. - General Message: A BRC-103 message of type
general, used to transmit an entire HTTP request or response under the authenticated session. - Peer: A user agent (client) or server implementing the protocol.
x-bsv-auth-Headers: A family of custom HTTP headers that store BRC-103 parameters (identity key, nonce, signature, etc.).x-bsv-paymentHeader: An optional header used for embedding BSV payment data (e.g. 402 flows)..well-known/authEndpoint: The canonical path for sending non-general messages as JSON in aPOSTbody.
5. High-Level Overview
- Non-General BRC-103 messages (initialRequest, initialResponse, certificateRequest, certificateResponse) are sent as:
- HTTP POST to
/.well-known/auth, with a JSON-serialized AuthMessage in the request body. - The server processes it, possibly returning an AuthMessage in JSON.
- HTTP POST to
- General BRC-103 messages are carried by a normal HTTP request to any path (e.g.,
/api/v1/orders), but encoded within custom headers plus a raw binary “payload.” - The server intercepts that request, reconstructs the “general” BRC-103 message, verifies signatures, and eventually returns a corresponding “general” BRC-103 response.
This layering effectively merges the BRC-103 handshake and certificate logic with standard HTTP request/response cycles.
6. Detailed Specification
6.1 HTTP Endpoints
MUST define at least one endpoint:
POST /.well-known/auth- Accepts a JSON body representing a BRC-103 AuthMessage (any non-general type).
- The server verifies the BRC-103 signature. On success, it MAY respond with another non-general BRC-103 message as JSON (e.g.
initialResponseorcertificateResponse). - If the handshake is incomplete or invalid, the server responds with an HTTP 4xx.
Other resource endpoints (e.g. /myapp/orders) MAY handle general messages. The request body is an ordinary HTTP request body, while key BRC-103 fields (signature, identityKey, etc.) are placed in custom headers and an encoded “payload.”
6.2 Header Conventions
BRC-104 introduces the following headers:
x-bsv-auth-version: The BRC-103 version string (e.g."1.0").x-bsv-auth-identity-key: The sender’s public identity key (33-byte compressed secp256k1 pubkey, typically hex).x-bsv-auth-nonce&x-bsv-auth-your-nonce: 32-byte ephemeral nonces used in BRC-103’s handshake.x-bsv-auth-signature: ECDSA signature in hex, verifying the message.x-bsv-auth-request-id: A client-generated 32-byte random ID (base64) to correlate request/response pairs in “general” messages.x-bsv-auth-message-type: (Optional) The BRC-103 message type if returning a certificateRequest or certificateResponse via HTTP.x-bsv-auth-requested-certificates: (Optional) JSON-encodedRequestedCertificateSetfor certificate requests.
x-bsv-auth- headers MUST be excluded from the set of user-signed headers. They are ephemeral parameters or are used for BRC-103 signature itself.
6.3 Signed Fields & Excluded Fields
When building a “general” message, the BRC-103 specification requires a signature across certain fields. In BRC-104:
-
Included in signature:
- Request method (
GET,POST, etc.). - Request path and query string.
- “Whitelisted” headers only:
authorization(client and server)content-type(client-only)- Any header with prefix
x-bsv-exceptx-bsv-auth-...
- Request body bytes.
- Request method (
-
Excluded:
- Non-whitelisted headers (like
x-bsv-auth-*,accept) - Cookies, user-agent, etc.
- Non-whitelisted headers (like
Servers do not sign content-type because certain server middleware tends to modify the content-type header. For example, express appends charset=utf-8 to the content-type resulting in ambiguity over the pre-image being signed.
Clients however do not generally modify the content-type header in requests which allows it to be included in the pre-image being signed.
The order of included headers will be lexicographical to ensure matching preimages on both sides.
6.4 Request/Response Flow for “General” Messages
Client perspective:
- Construct an HTTP request as usual, but store the entire method, path, query, selected headers, and body inside a “payload” field in the BRC-103 general message.
- The BRC-103 identity key, version, nonce, etc., go into
x-bsv-auth-*headers. - Send the request over standard HTTP.
- The server verifies authenticity, processes the request, and returns a BRC-103 “general” message in the response:
- The server includes
x-bsv-auth-version,x-bsv-auth-signature,x-bsv-auth-identity-key, etc. - The actual response status code, headers, and body are re-encoded as a “payload.”
- The server includes
Server perspective:
- On receiving the request, parse the
x-bsv-auth-*headers (nonce, signature, identityKey, etc.). - Construct the “general” BRC-103 message from the payload.
- If signature checks pass, handle the HTTP request in memory (similar to a normal route).
- Instead of sending the result directly to the wire, embed your final status code, headers, and body in a new “general” BRC-103 message.
- Write it back in
x-bsv-auth-*headers + the binary payload within the same HTTP response.
6.5 Request/Response Flow for “Non-General” Messages
Non-general BRC-103 messages—like initialRequest, initialResponse, certificateRequest, certificateResponse—MUST be exchanged via:
POST /.well-known/auth, with a JSON body:{ "version": "1.0", "messageType": "initialRequest", "identityKey": "...", "initialNonce": "...", "signature": "...", ... }- The server decodes the AuthMessage, verifies it, and possibly replies with another AuthMessage in JSON form:
{ "version": "1.0", "messageType": "initialResponse", "identityKey": "...", "nonce": "...", "yourNonce": "...", "signature": "...", ... } - On success, the client merges that result into the BRC-103 session state.
6.6 Authentication Failure Handling
- If the handshake or signature fails, the server MUST return
401 Unauthorized(or another 4xx suitable code) with a JSON body describing the error. - If the user sets invalid data, the server MAY respond with
400 Bad Request.
6.7 General Message Encoding Rules
When sending a “general” message:
6.7.1 Path Encoding Rules
- If the
pathhas a value, it must be serialized as UTF-8 bytes with a length prefix. - If the
pathis empty, it must default to/, serialized as UTF-8 bytes with a length prefix.
6.7.2 Query Parameter Encoding Rules
- If query parameters are present, the entire query string (including the leading
?) must be serialized as UTF-8 bytes with a length prefix. - If no query parameters are present, specify a length of
-1in the payload.
6.7.3 Body Encoding Rules
The body is included raw in the BRC-103 payload, but only after a length prefix.
a. If the content-type is application/json:
- The JSON object must be stringified and converted to UTF-8 bytes.
- If the body is empty, an empty JSON object
{}should be stringified and converted to UTF-8 bytes.
b. If the body consists of binary data (e.g. images):
- The binary is included directly as bytes.
- If the body is empty, specify a length of
-1in the payload.
The same rules apply to the server’s response body in a “general” response message.
6.8 Signature Preimage Calculation for HTTP Request Messages
BRC-103 specifies that the preimage is constructed by concatenating these fields in a fixed order:
x-bsv-auth-request-id(32 bytes, base64-decoded).- Request method: length + UTF-8 bytes.
- Path: length + UTF-8 bytes (use
/if the path is empty). - Query string (including
?): length + UTF-8 bytes (or-1if none). - Included headers: count them in canonical lexicographic order by lowercase header name. For each header:
- VarInt of key length, followed by key bytes
- VarInt of value length, followed by value bytes
- Body: length + body bytes (or
-1if none).
Finally, sign the preimage using the identity key. The server reconstructs the same preimage from the request data and verifies the signature contained in x-bsv-auth-signature.
6.9 Signature Preimage Calculation for HTTP Response Messages
In response to client request the server creates a BRC-103 payload as follows:
x-bsv-auth-request-id(echoing back the client's requestId as seen on line 174).- Response status (varInt)
- Included headers count, given in canonical lexicographic order by lowercase header name. For each header:
- VarInt of key length, key bytes
- VarInt of value length, value bytes
- Body length + body bytes (or
-1if none).
7. Implementation Notes & Examples
7.1 Client-Side Example
A reference “client” does the following:
- When sending a non-general message (e.g. handshake, certificate request), it:
- Performs
POST /.well-known/authwithContent-Type: application/json. - Embeds the entire AuthMessage (BRC-103 structure) in JSON.
- Performs
- When sending a general message:
- Serializes method, path, query, whitelisted headers, and body into a BRC-103 payload.
- Supplies
x-bsv-auth-version,x-bsv-auth-identity-key,x-bsv-auth-nonce,x-bsv-auth-your-nonce(if applicable),x-bsv-auth-signature, andx-bsv-auth-request-idin the request headers. - On receiving the server’s HTTP response, decodes those same fields from the response headers, building a BRC-103 message that includes the returned status code, headers, and body as a “payload.”
7.2 Server-Side Example
- Intercept
POST /.well-known/authrequests, parse them as JSON, treat them as BRC-103 “non-general.” - For other paths, it checks for
x-bsv-auth-request-idto see if it’s a “general” message. - It re-routes the normal Express request logic so that instead of returning data directly, the server packs the data into a BRC-103 “general” message and responds accordingly.
This approach ensures a typical server can remain mostly unmodified, while the middleware handles the signature verification and re-encoding of the final response.
8. Security Considerations
- Replay Attacks: The
noncefields in BRC-103 ensure freshness. Servers MUST reject repeated nonces. - Header Injection: Only a fixed set of headers is signed. If malicious headers are injected, they are outside the signature scope. Implementers should sanitize or ignore unknown headers.
- Transport Encryption: BRC-104 does not replace TLS. Implementers SHOULD still use HTTPS to hide private or sensitive information from eavesdroppers.
- Certificate Revocation: If identity certificates are used, the logic for checking revocationOutpoints remains as in BRC-103.
References
- BRC-103: Peer-to-Peer Mutual Authentication and Certificate Exchange Protocol (provides handshake and message definitions).