Personas prove what goes to relays; the server says what it reads
FEP-521a and FEP-8b32. Every persona has an Ed25519 key of its own (Avatar.SigningKey; migration 014 gives the earlier ones theirs), named in its actor's assertionMethod as a Multikey, the terms defined in the actor's own context. A persona's activity going to a relay carries an eddsa-jcs-2022 proof (JSON canonicalised by RFC 8785, Jcs), so what Activity-Relay forwards reaches Mastodon, which verifies it with its own code. Nothing else carries one: Mitra takes a proof over the HTTP signature and refuses one by a key it has not read, without reading the actor again. Received: an actor's own Multikeys are kept, and a forwarded activity whose proof one of them verifies is taken as it came instead of being read again from its origin. Discovery: WebFinger for the server's origin links its instance actor (FEP-d556), NodeInfo links it as the application actor (FEP-2677), and actors name RFC 9421 under implements (FEP-844e). Checked live: relay 16 (Activity-Relay's forward of alice's post reaches Mastodon), Mitra, GoToSocial and Mastodon unchanged (165 in all). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
This commit is contained in:
1 parent
c47b6e5533
commit
9ab87b2779
22 files changed
+702
-30
No files matched your search
@@ -79,9 +79,29 @@ namespace PrivaPub.Federation.Rendering
|
||||
["privacySettings"] = "sm:privacySettings",
|
||||
["wallPosting"] = "sm:wallPosting",
|
||||
["wallPostVisibility"] = "sm:wallPostVisibility",
|
||||
["allowedTo"] = "sm:allowedTo"
|
||||
["allowedTo"] = "sm:allowedTo",
|
||||
// FEP-521a keys and FEP-8b32 proofs, defined here rather than by the data-integrity and multikey contexts,
|
||||
// which strict JSON-LD readers would have to fetch
|
||||
["assertionMethod"] = new JsonObject { ["@id"] = "sec:assertionMethod", ["@type"] = "@id", ["@container"] = "@set" },
|
||||
["Multikey"] = "sec:Multikey",
|
||||
["controller"] = new JsonObject { ["@id"] = "sec:controller", ["@type"] = "@id" },
|
||||
["publicKeyMultibase"] = new JsonObject { ["@id"] = "sec:publicKeyMultibase", ["@type"] = "sec:multibase" },
|
||||
["DataIntegrityProof"] = "sec:DataIntegrityProof",
|
||||
["proof"] = new JsonObject { ["@id"] = "sec:proof", ["@type"] = "@id", ["@container"] = "@graph" },
|
||||
["cryptosuite"] = new JsonObject { ["@id"] = "sec:cryptosuite", ["@type"] = "sec:cryptosuiteString" },
|
||||
["proofValue"] = new JsonObject { ["@id"] = "sec:proofValue", ["@type"] = "sec:multibase" },
|
||||
["proofPurpose"] = new JsonObject { ["@id"] = "sec:proofPurpose", ["@type"] = "@vocab" },
|
||||
["verificationMethod"] = new JsonObject { ["@id"] = "sec:verificationMethod", ["@type"] = "@id" },
|
||||
["implements"] = new JsonObject { ["@id"] = "https://w3id.org/fep/844e/implements", ["@type"] = "@id", ["@container"] = "@set" }
|
||||
});
|
||||
|
||||
// what PrivaPub reads that a sender cannot tell from our documents (FEP-844e): RFC 9421 signatures, with RSA keys
|
||||
static JsonArray Implements() => new(new JsonObject
|
||||
{
|
||||
["href"] = "https://datatracker.ietf.org/doc/html/rfc9421",
|
||||
["name"] = "RFC-9421: HTTP Message Signatures"
|
||||
});
|
||||
|
||||
public static string Html(string markdown) =>
|
||||
string.IsNullOrEmpty(markdown) ? string.Empty : Markdown.ToHtml(markdown, Pipeline).Trim();
|
||||
|
||||
@@ -150,6 +170,20 @@ namespace PrivaPub.Federation.Rendering
|
||||
document["attributedTo"] = actor.Wardens;
|
||||
document["postingRestrictedToMods"] = actor.PostingRestrictedToModerators;
|
||||
}
|
||||
// what the server reads (FEP-844e): on the application actor itself, on any other as its generator
|
||||
if (actor.Kind == LocalActorKind.Application)
|
||||
document["implements"] = Implements();
|
||||
else
|
||||
document["generator"] = new JsonObject { ["type"] = "Application", ["implements"] = Implements() };
|
||||
// its Ed25519 key (FEP-521a), which signs the proofs its activities carry (FEP-8b32)
|
||||
if (!string.IsNullOrEmpty(actor.SigningKey))
|
||||
document["assertionMethod"] = new JsonArray(new JsonObject
|
||||
{
|
||||
["id"] = actor.AssertionKeyId,
|
||||
["type"] = "Multikey",
|
||||
["controller"] = actor.Uri,
|
||||
["publicKeyMultibase"] = Signing.IntegrityProofs.Multikey(Signing.IntegrityProofs.PublicKey(actor.SigningKey))
|
||||
});
|
||||
if (!string.IsNullOrEmpty(actor.PictureURL))
|
||||
document["icon"] = new JsonObject { ["type"] = "Image", ["url"] = actor.PictureURL };
|
||||
if (!string.IsNullOrEmpty(actor.ThumbnailURL))
|
||||
|
||||
Reference in new issue
Block a user