swicg / activitypub-http-signature

Repository for a SocialCG report on how HTTP Signature is used with ActivityPub
https://swicg.github.io/activitypub-http-signature/
11 stars 1 forks source link

Key pair for every actor vs single instance-wide key pair #57

Open SorteKanin opened 3 weeks ago

SorteKanin commented 3 weeks ago

I posted this question on socialhub.activitypub.rocks but I thought I'd also try here to see if anyone knows.

Is there any specific reason to have separate public/private keys for every single actor, rather than just using a single instance-wide public/private key pair?

I was checking out this document here and it kinda implies that there is no need for every actor to have their own key. The procedure (as I understand it) should work even if all actors use the same key.

The server is in control of all the keys anyway. So why create a new key pair for every actor? It seems redundant/unnecessary. Is it mostly for future compatibility, for instance for a possible future with end-to-end encryption? Or is it that if a private key got leaked or broken, it’s at least only for one actor and not all actors?

Are there any implementations that assume that every actor has their own key pair and wouldn’t work with a single key pair?

nightpool commented 3 weeks ago

There's no real practical reason except that it makes confused deputy attacks harder and reduces the amount of validation/the footgun potential of processing user's activities as the sending server.

On Thu, Aug 15, 2024, 7:24 AM SorteKanin @.***> wrote:

I posted this question on socialhub.activitypub.rocks https://socialhub.activitypub.rocks/t/key-pair-for-every-actor-vs-single-instance-wide-key-pair/4460 but I thought I'd also try here to see if anyone knows.

Is there any specific reason to have separate public/private keys for every single actor, rather than just using a single instance-wide public/private key pair?

I was checking out this document here https://swicg.github.io/activitypub-http-signature/#how-to-obtain-a-signature-s-public-key and it kinda implies that there is no need for every actor to have their own key. The procedure (as I understand it) should work even if all actors use the same key.

The server is in control of all the keys anyway. So why create a new key pair for every actor? It seems redundant/unnecessary. Is it mostly for future compatibility, for instance for a possible future with end-to-end encryption? Or is it that if a private key got leaked or broken, it’s at least only for one actor and not all actors?

Are there any implementations that assume that every actor has their own key pair and wouldn’t work with a single key pair?

— Reply to this email directly, view it on GitHub https://github.com/swicg/activitypub-http-signature/issues/57, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABZCV4RPBHWQNPGVDFBR23ZRS2Z7AVCNFSM6AAAAABMSJUPI6VHI2DSMVQWIX3LMV43ASLTON2WKOZSGQ3DQMJVHAYTONA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

snarfed commented 3 weeks ago

@nightpool is definitely right about the fediverse as it exists in the wild today. Users, their keys, and all of their activities/objects are usually tightly coupled to their server and accessible to their admins.

Having said that, it's worth noting that ActivityPub itself is much looser and doesn't specify those couplings nearly so tightly. There are also experimental FEPs like fep-ae97 for client signing, along with portable signatures like LD Sigs, fep-c390 identity proofs, and fep-ef61 portable objects, that decouple them even more aggressively.

SorteKanin commented 3 weeks ago

reduces the amount of validation/the footgun potential of processing user's activities as the sending server

@nightpool If it's not too much to ask, could you expand on this? What kind of footguns might appear due to using only a single key?

Users, their keys, and all of their activities/objects are usually tightly coupled to their server and accessible to their admins.

@snarfed I'm not sure what this has to do with coupling, but maybe I am misunderstanding your comment. I'm definitely still assuming that the server is in control of the singular key and all the users, so in that sense there is the same coupling as when each user has their own key.

snarfed commented 3 weeks ago

I'm definitely still assuming that the server is in control of the singular key and all the users, so in that sense there is the same coupling as when each user has their own key.

Right, that is the key assumption. It's broadly true on the fediverse today, but not universally, and it's not required. You can build a server that doesn't control or have access to user private keys and still fully implements AP. Users can generate their own keypairs, give their server their public keys, and sign all of their activities locally, in their client. fep-ae97 describes this and links to two implementations. It's obviously unusual, and there are open questions - and most other servers would have trouble interoperating, since eg LD Signature support is mixed at best, much less FEP-8b32 integrity proofs - but still.

nightpool commented 3 weeks ago

You can build a server that doesn't control or have access to user private keys and still fully implements AP

You cannot do this without exposing every user on your server to URI exhaustion or confused deputy attacks where you can trick remote servers into thinking users "liked"/"boosted" different statuses then they actually did.

For example, imagine the following scenario:

  1. User alice@a.com posts "I like coffee!" with the URI https://a.com/post/123
  2. User bob@b.com boosts it.
  3. User alex@a.com generates a new Create { Note } activity with the URI https://a.com/post/123 that says "I hate coffee!"
  4. Alex signs this locally and sends this to c.com, where they have followers. Then, they send bob's signed boost.
  5. Users on c.com sees that Bob hates coffee instead of loving it.

Additionally, there's a similar trivial DOS attack where Alex signs Notes with all of the same URIs as Alice's notes and races to send them to all of Alice's followers before she can.

I've posted this scenario many times before on the mailing list when this discussion has come up. It was a CVE that we fixed very early in Mastodon's life cycle.

There's no way to fix this without 1) throwing away message signing entirely (by e.g. validating every URI you get sent with a lookup, meaning that message signing provides no value) or 2) a new extension property restricting an actor's keys to only be valid for some subset of URIs.

snarfed commented 3 weeks ago

Great point! Chalk up yet another open question. Nothing's ever easy 😆 😢

SorteKanin commented 3 weeks ago

@nightpool shouldn't the server at a.com just return an error when alex@a.com tries to create the activity with a URI that already exists? Isn't this just a bug in the a.com server? Why is Alex allowed to create that activity?

nightpool commented 2 weeks ago

@SorteKanin Because in the system @snarfed proposes, alex@a.com is custodial of their keys, so the server at a.com is not involved. They sign the request and deliver it to b.com directly. This cannot happen unless you use separate keys per actor and then also give alex@a.com access to them

SorteKanin commented 2 weeks ago

But if a.com is never made aware of the activity because it is sent directly to b.com, how can Alex set an ID? I mean whatever Alex sets the ID to, that URL will not exist (or it will point to something else) since a.com never even saw the activity. I don't see how it makes sense to send an activity directly to a remote server like that without having the activity on your own server as well.