Beersy
BRC-104

HTTP Transport for BRC-103 Mutual Authentication

A peer-to-peer handshake still has to travel over ordinary web requests to with existing infrastructure. This says exactly which endpoints and headers carry it.

About Mutual authentication, both sides prove who they are, not just the server.

AlsoTransportCertificates

Ty Everett, Brayden Langleychanged 1 May 20269 min read

Reference for an AI

Everything an assistant needs to answer questions about BRC-104 accurately, including what it depends on.

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 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.

httpbrc-103 auth

The specification

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, 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 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 (, signatures, identity keys, requested certificates, etc.).
  • Mechanisms to 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-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 a POST body.

5. High-Level Overview

  1. 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.
  2. 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.”
  3. 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 or 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:

  1. x-bsv-auth-version: The BRC-103 version string (e.g. "1.0").
  2. x-bsv-auth-identity-key: The sender’s public identity key (33-byte compressed pubkey, typically hex).
  3. x-bsv-auth-nonce & x-bsv-auth-your-nonce: 32-byte ephemeral nonces used in BRC-103’s handshake.
  4. x-bsv-auth-signature: signature in hex, verifying the message.
  5. x-bsv-auth-request-id: A client-generated 32-byte random ID (base64) to correlate request/response pairs in “general” messages.
  6. x-bsv-auth-message-type: (Optional) The BRC-103 message type if returning a certificateRequest or certificateResponse via HTTP.
  7. x-bsv-auth-requested-certificates: (Optional) JSON-encoded RequestedCertificateSet 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- 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:

  1. 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.
  2. The BRC-103 identity key, version, nonce, etc., go into x-bsv-auth-* headers.
  3. Send the request over standard HTTP.
  4. 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:

  1. On receiving the request, parse the x-bsv-auth-* headers (nonce, signature, identityKey, etc.).
  2. Construct the “general” BRC-103 message from the payload.
  3. If signature checks pass, handle the HTTP request in memory (similar to a normal route).
  4. Instead of sending the result directly to the wire, embed your final status code, headers, and body in a new “general” BRC-103 message.
  5. 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:

  1. POST /.well-known/auth, with a JSON body:
    {
      "version": "1.0",
      "messageType": "initialRequest",
      "identityKey": "...",
      "initialNonce": "...",
      "signature": "...",
      ...
    }
    
  2. 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": "...",
      ...
    }
    
  3. 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 path has a value, it must be serialized as UTF-8 bytes with a length prefix.
  • If the path is 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 -1 in 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 -1 in 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:

  1. x-bsv-auth-request-id (32 bytes, base64-decoded).
  2. Request method: length + UTF-8 bytes.
  3. Path: length + UTF-8 bytes (use / if the path is empty).
  4. Query string (including ?): length + UTF-8 bytes (or -1 if none).
  5. 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
  6. Body: length + body bytes (or -1 if 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:

  1. x-bsv-auth-request-id (echoing back the client's requestId as seen on line 174).
  2. Response status (varInt)
  3. 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
  4. 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:
    1. Performs POST /.well-known/auth with Content-Type: application/json.
    2. Embeds the entire AuthMessage (BRC-103 structure) in JSON.
  • When sending a general message:
    1. Serializes method, path, query, whitelisted headers, and body into a BRC-103 payload.
    2. 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-id in the request headers.
    3. 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

  1. Intercept POST /.well-known/auth requests, parse them as JSON, treat them as BRC-103 “non-general.”
  2. For other paths, it checks for x-bsv-auth-request-id to see if it’s a “general” message.
  3. 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 . 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 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).
Was this helpful?

Search Beersy

Search standards by number, title, author or topic