FEP-ef61: Portable Objects

I guess you are specifically talking about the did:key method, which the FEP uses in its examples. But the FEP supports other DID methods too, and many methods supports rotating signing keys (verificationMethod) without changing the identity.

With those DID methods, the secret used to rotate the signing keys can (and is strongly recommended to) be different from the signing keys. Even if you choose to let the signing key in the custody of the gateway, you will hold the primary secret in your own device and only delegate the capability to sign the portable objects to the gateway’s signing key. If the gateway becomes malicious, you will simply revoke the old gateway’s key using your own secret.

2 Likes

This is untrue, in fact it is the opposite of the FEP:

Implementers MUST support the did:key method. Other DID methods SHOULD NOT be used, as it might hinder interoperability

It says “other methods might be considered” underneath, but I don’t think anybody has implemented any of them. Funnily enough, it looks to me like did:web and did:dns would bring us back to exactly where we started …

Can you explain how an AP server that holds an object which has 3 gateways in it, all of them dead, would discover the linked data?

This is also a good way to use FEP-ef61

It is not, other DID methods are allowed (SHOULD != MUST). There will be at least one additional recommended DID method before finalization.

It seems unlikely that three gateways would be offline at the same time.
You can also try to retrieve linked data from the server that delivered the activity to you, or from a random big instance.

IIUC, gateways are simply a recommended place that you can get a self-certifying object from. It’s like BitTorrent’s “acceptable source” (?as) parameter. You can obtain the data from anywhere, though – even a USB drive mailed to you, or reading /dev/random until it spits out data that hashes to correct signed value. Yes, it’s harder if all the known sources are unavailable, but not impossible. You just have to rely on out-of-band knowledge.

1 Like

I think saying “it it allowed” for a SHOULD NOT is a bit funny, but oh well.

We are adding so many modalities and implementation complications (and unspecified methods that might be added in the future) to Activitypub here that we might as well tell people that the protocol is dead. No server is gonna be able to interop with anything else because there’s going to be an explosion of possible configurations.

Just think about what you have to get exactly right in order to use any of this:

  • JSON normalization
  • yet another signature format (we already have two, this adds another one with entirely different semantic and multihash stuff and potentially different key schemes)
  • gateway resolution including complicated fallback logic (what happens if the objects returned by the gateways are different for example?)
  • an entirely different idea of trust and origin validation, potentially via multiple complicated DID resolution standards (unclear which, but left to the implementation), each with dozens or hundreds of pages of standard text

and you don’t just have to get this stuff right, you must be prepared for anybody else to send you these objects suddenly, and you must be bug-compatible with the n biggest implementations. Given the implementation surface of this, that is going to be a special hell.

So essentially what this FEP accomplishes (if it gets partially accepted by the community) is: it will crowd out small implementations or implementations which focus on a small dependency footprint.

A good overview of what it takes to implement this is the meta-issue on fedify, which has over a dozen sub-issues: FEP-ef61: Portable Objects · Issue #288 · fedify-dev/fedify · GitHub

You will most likely use a library (there’s plenty of ones) instead of implementing it by yourself. Moreover, JCS is arguably simpler than the c14n scheme of LD Signatures for which you advocate.

Yes, for good reason. HTTP (Message) Signatures are good for protecting a single inbox delivery request for a single server, but it is (among other reasons) bound to a single @authority and not suitable for forwarding. It simply serves a different use case than this FEP.

LD Signatures sign the object itself (as opposed to HTTP Message Signatures which sign (a portion of) an HTTP message) and is suitable for forwarding, but it is an abandoned draft spec (succeeded by the very VC spec which the FEP is based on) which had literally no security considerations and has seen a number of vulnerabilities in practice (disclaimer: I’m the finder and reporter of some of them, and even I cannot immediately recall the exact count of the vulnerabilities). It is based on the RDF data model, which most implementer do not sufficiently understand nor care (unfortunately, maybe?). The JCS more closely represents the data model expected by many of today’s implementations, and will thus simplify the problem for those implementations, instead of complicating it.

Every object is signed by the user themself (assuming that the key is self-custodial) so it’s not like the gateways can randomly make up different objects (and the gateways are trusted by the user to some extent anyway). But I agree that there should be a standard strategy to resolve such conflicts. Perhaps, publishers should always add the updated property when updating an object and consumers should use the most recent version?

The different trust and origin model is the whole point of the FEP, because DNS is not omnipotent. We have always seen its problem like takeover of .af domains by Taliban government, or registrars putting a premium ex post facto. Also, not everyone can afford and maintain a domain forever, and a cryptographic secret is much cheaper (if it ever costs some money).

Also it’s not like the FEP recommends random DID methods for no reason. I think you are trapped by a wrong dualism here. There is a reason that the BCP 14 has the SHOULD requirement in addition to MUST and MAY. The SHOULD NOT requirement allows implementers to adopt another DID method if there is a strong reason to do so, or experiment with another method. But it’s not encouraged to invent or adopt random method for no reason, since that would hinder interoperability as the FEP already points out. The SHOULD NOT requirement allows the spec to evolve without breaking backwards compatibility (unlike the MUST (NOT) requirement), and it’s already stated that the FEP is going to have an additional blessed method.

Remember that this FEP is still in the DRAFT status, and it adds nothing to just complain that it’s incomplete (especially if that’s a repetition of an already recognised problem). The whole purpose of this thread is to improve it, after all.

No, the FEP (or FEPs in general) will remain optional, and will not crowd out implementations by any means. Implementations will always have the discretion to not implement this FEP, at the expense of reduced efficiency and portability. You cited Fedify, but that looks to me to be an evidence that the maintainer considers it to be worth that effort.

1 Like

Regarding the implementation complexity: the first three implementers of FEP-ef61 are all relatively small projects, maintained by a single person without any external funding. We used three different programming languages: PHP, Go and Rust.

I am not saying that FEP-ef61 is easy to implement, but I think its core features (normalization, signatures, encodings, ‘ap’ identifiers) can be implemented by anyone.

If you know a simpler solution, feel free to submit a competing proposal. However, I doubt that it can be made simpler.

You can try to copy Nostr and use keys instead of DIDs, but then you would need to re-invent a mechanism for key rotation, which DIDs provide out of the box. You can replace integrity proofs with custom signatures, but then everyone would need to roll their own implementation instead of using a library. You can remove multibase and mandate a specific encoding, but what if chosen encoding has some unforeseen flaws? For example, base58-btc is slowly being phased out because it is hard to implement in constant-time.

There are other FEPs that also solve the migration problem, but they require cooperating servers, and usually involve URI rewriting, which IMO is a bigger problem for implementers.

slight tangent: JCS vs RDFC should be irrelevant here; it’s abstracted away by the cryptosuite

you could in theory forward HTTP messages with a Signature but this requires forwarding the entire HTTP message instead of just the body content, or forwarding the original input headers/material at least. but the RFC recommends against this because it’s usually not worth it vs terminating the signature after the first hop (you may or may not trust the proxy isn’t lying on behalf of some backend service, but the existence or non-existence of backend services should be completely opaque to you)

1 Like