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
@@ -15,11 +15,15 @@ namespace PrivaPub.Tests.Support
|
||||
readonly RSA _key = RSA.Create(2048);
|
||||
readonly bool _namesSharedInbox;
|
||||
readonly bool _hasWall;
|
||||
readonly string _ed25519;
|
||||
|
||||
// sharedInbox: whether its document names its server's shared inbox (endpoints.sharedInbox), as Mastodon's do; wall:
|
||||
// whether it has a wall (sm:wall, Smithereen's)
|
||||
public RemoteActor(Peer peer, string name, string origin = default, string type = "Person", bool sharedInbox = false, bool wall = false)
|
||||
// whether it has a wall (sm:wall, Smithereen's); ed25519: whether it has an Ed25519 key (FEP-521a) to prove what it
|
||||
// sends (FEP-8b32)
|
||||
public RemoteActor(Peer peer, string name, string origin = default, string type = "Person", bool sharedInbox = false, bool wall = false,
|
||||
bool ed25519 = false)
|
||||
{
|
||||
_ed25519 = ed25519 ? PrivaPub.Federation.Signing.IntegrityProofs.NewSeed() : default;
|
||||
Name = $"{name}{Guid.NewGuid():N}"[..20];
|
||||
Id = $"{origin ?? peer.A}/users/{Name}";
|
||||
Type = type;
|
||||
@@ -36,6 +40,13 @@ namespace PrivaPub.Tests.Support
|
||||
public string SharedInbox => Id.Split("/users/")[0] + "/inbox";
|
||||
public string Wall => Id + "/wall";
|
||||
|
||||
// the activity with its proof by this actor's Ed25519 key
|
||||
public JsonObject Prove(JsonObject activity)
|
||||
{
|
||||
activity["proof"] = PrivaPub.Federation.Signing.IntegrityProofs.Create(activity, Id + "#ed25519-key", _ed25519, DateTime.UtcNow);
|
||||
return activity;
|
||||
}
|
||||
|
||||
public JsonObject Document()
|
||||
{
|
||||
var document = new JsonObject
|
||||
@@ -58,6 +69,12 @@ namespace PrivaPub.Tests.Support
|
||||
document["endpoints"] = new JsonObject { ["sharedInbox"] = SharedInbox };
|
||||
if (_hasWall)
|
||||
document["wall"] = Wall;
|
||||
if (_ed25519 != default)
|
||||
document["assertionMethod"] = new JsonArray(new JsonObject
|
||||
{
|
||||
["id"] = Id + "#ed25519-key", ["type"] = "Multikey", ["controller"] = Id,
|
||||
["publicKeyMultibase"] = PrivaPub.Federation.Signing.IntegrityProofs.Multikey(PrivaPub.Federation.Signing.IntegrityProofs.PublicKey(_ed25519))
|
||||
});
|
||||
return document;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user