HTTP Transport for BRC-103 Mutual Authentication
Ty Everett (ty@projectbabbage.com)
Brayden Langley (brayden@projectbabbage.com)
1. Abstract
This specification defines how to transport BRC-103 [1] mutual authentication messages via HTTP. It introduces:
A
.well-known/auth
endpoint 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-auth
headers 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-payment
Header: An optional header used for embedding BSV payment data (e.g. 402 flows)..well-known/auth
Endpoint: The canonical path for sending non-general messages as JSON in aPOST
body.
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.
initialResponse
orcertificateResponse
).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-encodedRequestedCertificateSet
for 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.
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:The server decodes the AuthMessage, verifies it, and possibly replies with another AuthMessage in JSON form:
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 Body Encoding Rules
When sending a “general” message:
The body is included raw in the BRC-103 payload, but only after a length prefix.
If
content-type
isapplication/json
, you typically convert your JSON object to UTF-8 bytes.If it is binary data (e.g. images), you pass the binary as bytes.
If no body, specify a
-1
length in the payload.
The same approach is used for the server’s return body in the “general” response message.
6.8 Signature Preimage Calculation for HTTP Request Messages
The code references BRC-103’s standard approach: concatenating these fields in a stable order:
x-bsv-auth-request-id
(32 bytes, base64-decoded).Request
method
length + UTF-8 bytes.Path length + UTF-8 bytes (or
-1
if empty).Query string length + UTF-8 bytes (or
-1
if none).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
-1
if none).
Then sign with the identity key. The server reconstructs that same preimage from the request data, verifying the signature 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
-1
if 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/auth
withContent-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
, andx-bsv-auth-request-id
in 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/auth
requests, parse them as JSON, treat them as BRC-103 “non-general.”For other paths, it checks for
x-bsv-auth-request-id
to 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
nonce
fields 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