How-to

Build a multi-hop relay

Applies to: .NET SDK Last updated: 2026-06-24

Goal

Build a chain where a message passes through several intermediate agents (A, B, C, D) before reaching the final recipient (alice). Bridge handles the crypto for arbitrarily deep chains; the application owns the transport and the orchestration. The chain is sequential — each peel feeds the next — but which intermediate peels first, second, third, etc. is the application's choice.

Not Tor — peel order is the application's choice

Unlike onion routing where each layer must be stripped in a strict outer-to-inner sequence on a predetermined path, HexaEight's intermediate peel (DecryptMessageUsingSharedKeyPreAsync) is commutative across peelers. The N intermediates can be applied in any permutation; each Pre still takes the previous peel's output as its input (you cannot peel the original ciphertext in parallel and join the outputs), but whichever order you choose, the final recipient's MultiDecrypt recovers the same plaintext.

Functions involved

Originator (one call)

// Chain: A → B → C → D → alice
string chain = "A.example.com;B.example.com;C.example.com;D.example.com;[email protected]";

// Fetch the multi-shared key for the whole chain at this kgt
string multiAsk = await originator.FetchDestinationAskAsync(
    logintoken: originatorToken, kgt, destination: chain);

string ct0 = await originator.MultiEncryptMessageUsingSharedKeyAsync(
    chain, "payload", multiAsk);

// Send ct0 to A via your transport, alongside (kgt, original_sender = self).

Each intermediate hop (identical code, different keys, order-agnostic)

// On any intermediate (A, B, C, or D) — they can run this in any order.
string askSelf = await selfClient.FetchAskAsync(originalSender, kgt);
string ctOut   = await selfClient.DecryptMessageUsingSharedKeyPreAsync(ctIn, askSelf);

// (optional) Casbin policy check before forwarding
var decision = await selfClient.Authorization.AuthorizeAsync(
    sender: originalSender, destination: finalRecipient,
    direction: "outbound", sessionId: selfClient.Name);
if (!decision.Allowed) return;

// Hand off (ctOut, kgt, original_sender, sender_agent = self) to wherever
// makes sense for your workflow — the next sequential hop, a join
// aggregator, or directly to alice once all intermediates have peeled.

Topology choices the application owns

Because peel order is freely chosen, the same N-intermediate set works under several sequential routings:

What is not possible: peeling the original ciphertext at multiple intermediates in parallel and joining their outputs. Each Pre consumes the output of the previous Pre, so the application must serialize the peel calls — it just gets to pick the order.

Final recipient (one call)

// On alice
string aliceAsk = await alice.FetchDestinationAskAsync(
    logintoken: aliceToken, kgt,
    destination: "~D~" + originalSender);

string plaintextEnvelope = await alice.MultiDecryptMessageUsingSharedKeyAsync(
    ctIn, aliceAsk);

// plaintextEnvelope.RECEIVER carries the full chain that was bound at encrypt time:
//   "A.example.com;B.example.com;C.example.com;D.example.com;[email protected]"
// — a missing or substituted hop fails the peel cryptographically.

Transport and orchestration are the application's job

Bridge does not orchestrate the hops. The application chooses how to move (ciphertext, kgt, original_sender, sender_agent) from one peeler to the next — HTTP, MQ, file drop, whatever. The crypto chain is correct as long as each intermediate calls DecryptMessageUsingSharedKeyPreAsync with the right (self, originator) ASK exactly once (in any order), and the final recipient calls MultiDecryptMessageUsingSharedKeyAsync with its own (self, originator) ASK after every intermediate has peeled.

Content signatures and chain-of-custody

If the original sender signs the body with the HexaEight signing library before calling MultiEncryptMessageUsingSharedKeyAsync, the signed-body bytes are part of the encrypted payload and are recovered intact only at the final recipient's MultiDecrypt. Intermediates never see the signed body — they only strip their layer of the wrapper. The final recipient can verify the signature for cryptographic proof of origin without trusting any intermediate.

See also