What Does an MPC Relay Server Know, and What Does It Forward?
Even when a private key is distributed among several people, joint signing still requires them to connect. Someone must check who is online, select the participants for this transaction, and deliver the messages produced during computation. If a server handles these tasks, a new question arises. Is the server using the key on their behalf, or connecting the key holders so they can compute together?
The answer depends on the information the server receives and the operations it performs, rather than its name. Authority to forward a message, authority to decrypt it, and authority to sign a wallet transaction are different things. We will follow these boundaries through BXB's communication between users and its separate encrypted relay module.
The next transfer of 10 tokens needs a new session
Suppose address A holds 90 units of token T on an EVM network, and address B holds 10. A's wallet is a 2-of-3 wallet: two of P1, P2, and P4 must participate to produce a signature. P4 has replaced a previous participant, and all three hold their own current key shares. The change of participants did not move any tokens. Now, in a separate transaction, A will send another 10 T to B.
Assume T has zero decimal places, with no minting, burning, token transfer fees, or concurrent transactions. A separately holds the native currency needed to pay transaction fees. If the transfer succeeds, A will have 80 T and B will have 20 T. This is an illustrative outcome, not a measurement from an executed transfer.
P1 and P4 will sign this transaction. They do not assemble their private key shares on a server. Instead, each computes with its own share and exchanges the necessary messages to produce one ECDSA signature. Joint signing without assembling the private key explains why this computation is possible. Here, we will look at how its messages are tied to the same task.
Even if P1 and P4 handle a later transaction together, they cannot simply continue using the previous messages. A new transaction needs a new signing input and session. A session identifies one execution in which the selected participants perform a particular task together. It is the starting point for keeping messages separate from other transfers using the same wallet or from an earlier set of participants.
Coordination, delivery, and computation
Joint signing involves three roles. They may live in the same program, but their responsibilities should be understood separately.
| Role | What it handles | What this alone does not complete |
|---|---|---|
| Session coordination | Participant selection, invitations, start, and expiry | Producing a wallet signature |
| Message delivery | Transport between connected senders and recipients | Checking the validity of cryptographic computations |
| Participant computation | Computing with locally stored material and received messages | Confirming on-chain execution |
In BXB's user-only signing flow, the extension exchanges messages with other users over PeerJS connections. A server handles connection signaling, invitations, and progress, while the actual signing computation runs in each participant's WebAssembly module. The extension retrieves outgoing messages from the module, sends them, and feeds received messages back into it. Determining whether the cryptographic module can proceed is a different task from determining whether a network connection is open.
The source also contains a separate cowork relay module for user and server participants. It relays encrypted envelopes over WebSocket and makes the participant specification and message protection more explicit. The session envelope and HPKE explanations in this article concern the client, relay, and encryption components found in that separate module. They do not imply that the user-only PeerJS flow uses the same envelope, or that the two flows together form one demonstrated signing process involving a server participant.
P1 and P4's transfer is therefore a shared example for understanding the roles. We will use the same names when explaining envelopes, without implying that every component's interoperability and on-chain execution have been reproduced in a particular deployment.
Why a participant list also needs key versions
Before signing begins, is it enough to agree that P1 and P4 will participate? Even for the same P4, a new device may have a different registered transport key from last month's device. The wallet address may remain unchanged while the stored key shares differ before and after a participant replacement. If only the names match and the other conditions differ, delivering messages will not be enough to perform the same computation.
A session specification that collects these conditions is called a manifest. BXB's separate relay manifest includes the session ID, operation type, participation requirements, expiry time, and participant list. Wallet and transaction request identifiers, the message to be signed, and the share version are also included according to the operation's inputs. Each participant entry connects the ID used in cryptographic computation with its user or server type, transport public key, and key version.
In particular, shareVersion and keyVersion answer different questions.
The former identifies which generation of wallet shares is used for joint signing; the latter identifies which device and transport keys are used to exchange messages.
Replacing P4's communication key does not automatically reshare the wallet key.
Conversely, receiving a new wallet share does not automatically retire every communication credential held by an old device.
The manifest is also identified by a manifestHash.
The server applies SHA-256 to a representation with a consistent ordering of object fields.
This avoids treating the same field contents as different simply because the JSON object's fields were written in a different order.
The envelope carries this hash instead of the full manifest, linking the message to its specification.
A matching hash establishes that the referenced content matches. It does not prove that whoever created the manifest selected the right transaction, or that the public keys in it were trustworthy in the first place. Trustworthy manifest distribution and participant and public-key registration are also needed.
Wallet keys, device identity keys, and transport keys
Calling everything P4 holds a "key" obscures the different roles. Material used to participate in wallet signing serves a different purpose from material used to decrypt messages.
| Material | Where it is used | What it checks or does |
|---|---|---|
| A wallet's ECDSA secret share | Joint signing module | Computes a wallet signature with other participants |
| An Ed25519 device identity key | Device public-key registration | Checks the relationship between a registration request and key possession |
| An X25519 transport key | HPKE recipient | Opens messages encrypted for that recipient |
The registration flow in BXB's extension generates separate Ed25519 and X25519 keys. It uses the Ed25519 key to sign registration content that binds the server's one-time challenge, the user identifier, and both public keys. The server checks the signed-in user and challenge, then verifies the registration signature. This process links the transport public key being registered to a particular user's request.
User authentication on the relay WebSocket instead uses a login token, while server participants use separate connection credentials. The Ed25519 signature used for registration should not be understood as automatically accompanying every subsequent relay envelope. Proof of key possession during registration, authentication of the currently connected party, and cryptographic protection of individual messages are separate stages.
Holding an X25519 recipient key does not let someone produce the wallet's ECDSA signature alone. Holding a wallet share does not grant access to every session on the server either. When replacing a device or disabling an account, an operator needs to distinguish which material and credentials are being changed. Storing them on the same device does not make them the same key.
Why encrypt a message on top of a TLS connection?
Suppose P1 connects to the relay server over TLS, and the server also has a TLS connection to P4. TLS protects each connection against eavesdropping and tampering, but if the server is an endpoint, that connection's encryption terminates there. Protecting the connection alone therefore does not mean the server cannot read the application payload. Where protection terminates matters, as described by the TLS 1.3 channel model.
The PeerJS flow between users uses a different communication structure: WebRTC data channels. WebRTC data channels are protected by DTLS, with connection signaling and the data channel serving distinct roles. The WebRTC security architecture explains this model. This does not amount to verification of every connection setting or participant authentication mechanism in an individual BXB deployment.
HPKE in the separate cowork module protects the payload carried over the relay connection for the recipient's public key. HPKE stands for Hybrid Public Key Encryption. It uses public-key operations to establish the required secret and symmetric encryption to process the payload. Its three key components are KEM, KDF, and AEAD, as set out in RFC 9180.
First, in the KEM, or key encapsulation mechanism, P1 uses P4's public key and a freshly generated ephemeral secret.
This produces a shared secret and an encapsulated value, enc, to send.
P4 obtains the same shared secret using its own private key and enc.
In the X25519 construction examined here, enc is an ephemeral public key, not an encrypted copy of P1's wallet secret share.
Next, the KDF, or key derivation function, derives the actual encryption key and other required values from the shared secret and its context. The module uses HKDF-SHA256. HKDF extracts keying material from its input and expands it to the required length using information about its purpose and context. The HKDF specification also explains why values for different purposes need to be distinguished.
Finally, AEAD, or authenticated encryption with associated data, encrypts the MPC message payload and produces an authentication tag.
This module uses AES-256-GCM. The recipient uses the same context to verify and decrypt the message,
rejecting data that fails verification.
The relay carries this ciphertext, enc, and the outer information needed for delivery.
Binding the envelope's addressing information to its payload
Even with an encrypted payload, the labels saying which session it belongs to and who should receive it cannot be treated as unrelated information. A message from P1 to P4 for the current transfer must not be relabeled as belonging to an earlier session. This binding uses AAD, Additional Authenticated Data. AAD is additional information verified together with the ciphertext but not hidden through encryption. The AEAD interface takes the payload and AAD as separate inputs.
This BXB envelope includes the session ID, sender and recipient, message ID, sequence number, operation label, and manifest hash in its AAD.
For one message from P1 to P4, the relationship can be shown as follows.
S-new and msg-7 are illustrative names.
Session: S-new
From: P1
To: P4
Message: msg-7 / seq 7
Operation: SIGN
Manifest: session hash
↓ bound as AAD
Encrypted MPC payload
The recipient reconstructs the same AAD from the envelope and uses it for decryption.
If the existing ciphertext is left unchanged but the session or recipient is altered, verification fails because the context no longer matches the one protected with it.
The cryptographic module examined here also binds this context into HPKE's key derivation info.
The envelope's aadHash identifies and checks the AAD; a hash that anyone can compute is not itself a substitute for authentication using a secret key.
The recipient must still check whether this is the session context it expects. Matching the names used during encryption and decryption does not, by itself, grant business authorization to participate in that session. The relay's session and manifest checks and the recipient's ciphertext verification thus establish different conditions.
The relay can see the information placed in AAD. It needs to know the recipient and session to decide where to forward the envelope. Having an encrypted payload alongside visible routing information is an intentional distinction in this structure.
Sequence numbers and protocol rounds serve different purposes
What happens if P1's envelope arrives twice, or an earlier message arrives late? A valid ciphertext alone does not reveal whether this is the first time the message has been processed. Session state is also needed to distinguish replay, the resending of a previously valid ciphertext, and duplicates introduced during communication.
The relay code examined here rejects a messageId that has already been used in the same session.
The seq value must increase for each sender-recipient pair within that session.
For example, if the last P1→P4 value was 7, neither 7 nor 6 is accepted.
P4→P1 has its own sequence. This check does not guarantee that numbers are consecutive or that missing messages have been recovered automatically.
The round field also needs to be distinguished. In this signing envelope, round is the operation label SIGN.
It does not mean the relay server uses this field to determine the first or second mathematical round inside the threshold signing algorithm.
Processing the actual cryptographic protocol messages and advancing to the next stage are responsibilities of the computation module receiving the payload.
Correct delivery order and cryptographic suitability for the next computation are different conditions.
The name nonce likewise covers three different roles here. An account's transaction nonce distinguishes the order of on-chain transactions. The secret ECDSA nonce is a secret value used in signing. An AEAD nonce need not be secret, but must not repeat when encrypting under the same symmetric key. It is not a place to simply reuse a transaction sequence number or signing secret. The one-time challenge received during device registration also belongs to that particular registration procedure.
The envelope's seq and HPKE's internal encryption counter are not automatically the same value either.
In the Go module examined here, an envelope encryption call creates a fresh ephemeral key and HPKE context,
and derives the AEAD nonce within that context. The application sequence number is included separately in the AAD.
Names alone do not determine which communication objects can be reused and which cryptographic material must not be reused.
HPKE itself does not manage duplicates and restarts across every session. RFC 9180's discussion of replay also limits the scope of its protection. Duplicate detection records, session lifetimes, and recipient processing results need to be managed together. A sequence number alone does not establish exactly-once delivery or processing.
What the server knows is different from what it can sign
We can now identify what the relay server can see. For the separate HPKE envelope, it can see which connected party sends to whom in which session, along with the message ID, sequence number, operation label, key versions, and ciphertext size. Timing and frequency may also reveal progress through a task. If the coordination server also prepares transactions, it may know the transaction details supplied for that work. Payload encryption does not hide all business information from the server.
The module, however, is designed to open the payload using the recipient's transport private key. The relay server's envelope handling does not include computing signatures with participants' wallet shares. Seeing a message, storing a ciphertext, and having enough participants' secret material to sign for a wallet are different things.
The phrase authenticated sender also needs a clear scope.
The BXB relay assigns from based on the identity established during connection authentication.
It checks that this party and the recipient are included in the session manifest and that the envelope's key versions match it.
This is a trusted relay binding an authenticated connection to a sender label.
The HPKE base mode used here does not, by itself, prove possession of P1's long-term identity key. Anyone who knows P4's public key can create a new ciphertext that P4 can open. Successful decryption therefore cannot be treated as evidence that P1 personally signed the envelope. The connection authentication and manifest distribution on which sender identification relies must also be considered. HPKE's authentication modes explain these distinctions.
Finally, a valid ciphertext from an allowed participant can still contain an invalid MPC message. The transport layer checks the ciphertext and context, while the cryptographic computation module checks the messages and proofs required by its protocol. The business application must separately check the recipient, amount, and authorization. Success at any one of these checks does not replace the others.
A server that cannot read a message can still stop the computation
Even if a relay lacks the recipient's private key and cannot open the payload, it can still disconnect a connection or delay message delivery. If P1 and P4 do not receive the messages they need, joint signing cannot proceed even while each keeps its key share secure. Protecting secrets and keeping a task available are different properties.
The relay examined here checks session state, expiry, and connectivity and reports delivery results. The client also has a flow for waiting for messages and handling session failure. But a delivery response from the relay does not establish that P4 has finished decryption and cryptographic computation. Reconnecting is likewise not evidence that every computation state from before the interruption has been safely restored. Rather than inserting P2 into the ongoing P1–P4 session, the participants and one-time material must be handled afresh according to the protocol.
If our example stops before the signature is complete and no transaction is submitted, the balances remain 90 T for A and 10 T for B. That unsubmitted attempt incurs no on-chain fee. If the transaction has already been submitted but its response was lost, check its on-chain status first instead of creating another transfer solely because the relay interface shows a failure.
Even after joint signing and submission, the execution receipt and required level of confirmation must be checked separately. Only when this transfer actually succeeds can the example close with 80 T for A and 20 T for B, while the transaction fee is deducted separately from A's native currency balance. A transaction included on-chain may consume gas even if execution fails, so that case must also be distinguished from stopping before submission.
An MPC relay keeps multiple participants' computations connected within the same session. The manifest defines who computes together and under what conditions; message protection binds the payload to its delivery context; and each participant's cryptographic module uses those inputs to compute the joint signature. Looking at where these responsibilities and authorities meet and where they end, rather than merely whether a server exists, shows what a design based on distributed key shares requires from its communication and operations.