How-to
Verify the original sender
Goal
Confirm who actually originated a relayed message, and decide what stronger guarantees you want on top of what the crypto itself proves.
What the crypto proves
When the final recipient calls Client.MultiDecryptMessageUsingSharedKeyAsync and gets a non-empty plaintext, that plaintext envelope's SENDER and RECEIVER fields are cryptographically authentic — the multi-shared key was derived for that exact (sender, chain) tuple at encrypt time, and a substituted intermediate or wrong final recipient would fail the peel chain. So you do not need additional trust to believe the SENDER field on a successfully decrypted multi-party message.
// On the final recipient
string aliceAsk = await alice.FetchDestinationAskAsync(
logintoken: aliceToken, kgt, destination: "~D~" + claimedOriginator);
string plaintextEnvelope = await alice.MultiDecryptMessageUsingSharedKeyAsync(
innerCiphertext, aliceAsk);
if (string.IsNullOrEmpty(plaintextEnvelope)) {
// Decrypt failed — either claimedOriginator is wrong, a hop was skipped,
// or the ciphertext was tampered with. Reject.
return;
}
using var doc = JsonDocument.Parse(plaintextEnvelope);
string sender = doc.RootElement.GetProperty("SENDER").GetString() ?? "";
string receiver = doc.RootElement.GetProperty("RECEIVER").GetString() ?? "";
// sender == claimedOriginator now is guaranteed (decrypt would have failed otherwise)
ProcessMessage(sender, receiver, doc.RootElement.GetProperty("BODY").GetString()); Pattern — non-repudiation via content signature
The decrypted SENDER tells you who originated the message at this kgt window, authenticated by the platform-derived multi-shared key. For non-repudiable, transport-independent proof that lasts beyond the kgt window (audit logs, legal evidence), have the originator sign the body before encrypting:
// On the originator (functions involved):
// signingClient.SignContent(body)
// Client.FetchDestinationAskAsync(logintoken, kgt, chain) // multi-shared key
// Client.MultiEncryptMessageUsingSharedKeyAsync(chain, signed, multiAsk)
string signed = signingClient.SignContent(plaintextBody);
string multiAsk = await origin.FetchDestinationAskAsync(originToken, kgt, chain);
string ct = await origin.MultiEncryptMessageUsingSharedKeyAsync(chain, signed, multiAsk); // On the final recipient (after MultiDecrypt):
bool isAuthentic = signingClient.VerifySignature(
body: extractedBody, expectedSigner: sender);
if (!isAuthentic) { /* tampered or wrong signer */ return; } See also
- Trust and verification Concept
- Forward a message to a final recipient How-to
- Build a multi-hop relay How-to