HTTP Transport for BRC-103 Mutual Authentication
- Ty Everett ([email protected]) 
- Brayden Langley ([email protected]) 
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, or- general.
- Non-General Message: A BRC-103 message of type - initialRequest,- initialResponse,- certificateRequest, or- certificateResponse.
- 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 a- POSTbody.
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. 
 
- 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. - initialResponseor- certificateResponse).
- 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-encoded- RequestedCertificateSetfor 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-except- x-bsv-auth-...
 
- Request body bytes. 
 
- Excluded: - Non-whitelisted headers (like - x-bsv-auth-*,- accept)
- Cookies, user-agent, etc. 
 
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.” 
 
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 the order they are transmitted. 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 order of transmittal over the wire. 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/authwith- Content-Type: application/json.
- Embeds the entire AuthMessage (BRC-103 structure) in JSON. 
 
- 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, and- x-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). 
Last updated
