FEP-c390: Identity Proofs

Hello!

This is a discussion thread for the proposed FEP-c390: Identity Proofs.
Please use this thread to discuss the proposed FEP and any potential problems or improvements that can be addressed.

Summary

This proposal describes a mechanism of creating verifiable links between Decentralized Identifiers and ActivityPub actor profiles.

Potential applications include: identity verification, end-to-end encryption and account migrations.

2 Likes

Hello!

This is a discussion thread for the proposed FEP-c390: Identity Proofs. Please use this thread to discuss the proposed FEP and any potential problems or improvements that can be addressed.

Summary
This proposal describes a mechanism of linking cryptographic keys to ActivityPub actor profiles.

2 Likes

@silverpill you should probably include in the example the DID @context which i assume you are pulling vocabulary from

1 Like

It’s a mixed bag.

The proof property comes from Data Integrity standard, which uses https://w3id.org/security/data-integrity/v1 context in this example: A simple signed JSON-LD data document.

The Identity type was suggested by someone in W3C wiki: Linking Identities. It is also necessary to make a distinction between FEP-c390 identity proofs and Mastodon identity proofs (which have IdentityProof type).

id and alsoKnownAs properties were indeed borrowed from the DID spec, which requires https://www.w3.org/ns/did/v1 context to be present in DID documents, but FEP-c390 attachment is not a DID document, strictly speaking.

What would be the best course of action here?

all of those should be included in the context then, and any new properties should be defined as an extension in your own context

prior art: see any as2 doc generated by mastodon and how it includes the Security context as well (among other things):

https://mastodon.social/users/trwnh.json

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/v1",
    {
      "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
      "toot": "http://joinmastodon.org/ns#",
      "featured": {
        "@id": "toot:featured",
        "@type": "@id"
      },
      "featuredTags": {
        "@id": "toot:featuredTags",
        "@type": "@id"
      },
      "alsoKnownAs": {
        "@id": "as:alsoKnownAs",
        "@type": "@id"
      },
      "movedTo": {
        "@id": "as:movedTo",
        "@type": "@id"
      },
      "schema": "http://schema.org#",
      "PropertyValue": "schema:PropertyValue",
      "value": "schema:value",
      "discoverable": "toot:discoverable",
      "Device": "toot:Device",
      "Ed25519Signature": "toot:Ed25519Signature",
      "Ed25519Key": "toot:Ed25519Key",
      "Curve25519Key": "toot:Curve25519Key",
      "EncryptedMessage": "toot:EncryptedMessage",
      "publicKeyBase64": "toot:publicKeyBase64",
      "deviceId": "toot:deviceId",
      "claim": {
        "@type": "@id",
        "@id": "toot:claim"
      },
      "fingerprintKey": {
        "@type": "@id",
        "@id": "toot:fingerprintKey"
      },
      "identityKey": {
        "@type": "@id",
        "@id": "toot:identityKey"
      },
      "devices": {
        "@type": "@id",
        "@id": "toot:devices"
      },
      "messageFranking": "toot:messageFranking",
      "messageType": "toot:messageType",
      "cipherText": "toot:cipherText",
      "suspended": "toot:suspended",
      "focalPoint": {
        "@container": "@list",
        "@id": "toot:focalPoint"
      }
    }
  ],
  "id": "https://mastodon.social/users/trwnh",
  // ...
}

note that mastodon currently inlines the context instead of actually hosting a jsonld document at joinmastodon.org/ns (which it should do, ideally)

2 Likes

(How) does this relate to GitHub - chatternet/chatternet-client-http ? Should it?

1 Like

Added missing contexts: #35 - FEP-c390: Add missing contexts - fep - Codeberg.org. I don’t know how to create my own context, so I used https://codeberg.org/fediverse/fep namespace for Identity type. The example now passes JSON-LD validation.

They also rely on DID and VC Data Integrity standards. There’s definitely some overlap, I think we can work together to make our implementations interoperable.

1 Like

Thanks to silverpill for bringing this to my attention. Indeed I’ve been working on Chatter Net which shares some ideas with this proposal overlaps. Currently in Chatter Net actors documents look like this:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://www.w3.org/2018/credentials/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW/actor",
  "type": "Person",
  "inbox": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW/actor/inbox",
  "outbox": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW/actor/outbox",
  "following": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW/actor/following",
  "followers": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW/actor/followers",
  "name": "Garrin",
  "proof": {
    "type": "Ed25519Signature2020",
    "created": "2022-11-26T18:58:47Z",
    "verificationMethod": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW#z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4iLgh38ipTKSVdvNttjJpGWP5kYZ5dv5jHaupwNjZmC6kpifnd4Ep7jV2A5pnYTVKoDvQdi4CYj2hAq5qR4cLMvh"
  }
}

Some notes as they relate to this discussion:

  • A DID should be the ID of a DID document. So in Chatter Net the /actor path is added to DIDs to differentiate the Activity Stream Actor object from the DID doc. You can see in this in action by requesting a DID document versus an Actor object.
  • Indeed wherever the proof key shows up the credential context will be needed, or the proof key could be fully expanded.

One thing to note is that Chatter Net currently isn’t using Activity Stream compliant messages because of the addition of the proof key in the object root, which isn’t part of the Activity Stream standard. These proofs are used not just for a user to assert things about their identity, but also to assert actions they take (i.e. assertion proofs are also added to activities such as Create).

Maybe this proposal could be extended to propose a new object type which isn’t just an Identity proof, but generally an Assertion proof? This way such an object could be added as an attachment to any document to assert something about the document?

It is also probably worth considering whether or not this is best done by instead introducing a assertion property to the base Activity Stream Object? This is would look more like what Chatter Net is currently doing, and be more convenient from the app development point of view because extracting a proof would require only looking up a key instead of traversing an array.

2 Likes

@silverpill, great job on the Identity Proofs FEP! It looks really good.

So this coming Tuesday Nov 29th, the W3C Credentials Community Group (where DIDs and VCs were incubated) is going to host a call on DIDs in Federated Social Web apps. (Here’s the post announcing it to the SocialWeb CG: Join the CCG "DIDs (Decentralized Identifiers) in ActivityPub/Fediverse" conversation from Dmitri Zagidulin on 2022-11-26 (public-swicg@w3.org from November 2022) )

I’ve also sent a link to your Identity Proofs FEP to the CCG mailing list, as suggested pre-call reading.

You should join the call on Tuesday, if you’re able! (The CCG is free to join, anyone can attend the calls).
(This goes for everyone on this thread, who’s interested in the topic).

4 Likes

There’s another proposal that describes the use of data integrity proofs for authenticating activities, perhaps it will be more appropriate for your use case: fep/fep-8b32.md at main - fep - Codeberg.org.

I picked attachment property for identity proofs because attachments are already used in Fediverse to add various metadata to actor profiles (e.g. PropertyValue attachments), so many applications would be traversing this array anyway. This also allows actors to link several identities to their profiles.

2 Likes

Is there a way to shorten this instead of repeating the same (difficult to read) value, e.g.:

  "inbox": "@id:/actor/inbox",
  "outbox": "@id:/actor/outbox",

Neat idea. I’m not familiar with the “@id:” syntax in a json-ld string, would that expand to the full URL? I think this could also be achieved by adding a base URL to the context and then using relative URLs. I might opt for that as I think it will play nicer with the expansion algorithms? Or am I missing something?

I did not test anything, this is just a hunch, but indeed it would make the data more readable and lighter, at the expense, maybe of increased parsing.

Non-normative, sure: JSON-LD 1.1 5.2.1 Shortening IRIs

You can use @base in your @context to add a “base IRI” like so:

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
    "@base": "did:key:z6MkiB1ykfZH2h91GDmY8Nh7iEiVzJX9KP5gvsshtfmpnfwW"
    }    
],
  "@id": "/actor",
  "inbox": "/actor/inbox",
  "outbox": "/actor/outbox",
  // ...
}

This requires support from your JSON-LD (specifically JSON-LD 1.1) parser, so ecosystem support would not be very widespread.

It’s also currently broken in the JSON-LD playground: JSON-LD Playground

{
  "@id": "did:/actor",
  "http://www.w3.org/ns/ldp#inbox": {
    "@id": "did:/actor/inbox"
  },
  "https://www.w3.org/ns/activitystreams#outbox": {
    "@id": "did:/actor/outbox"
  }
}

@trwnh - I think my question is, how often are you reading raw json? I’d personally recommend against doing relative URLs like that. In terms of how much room they take up over the wire, or in storage – don’t forget that everything basically uses gzip over the wire, so all those repeating URLs or whatever will be compressed down anyway.

2 Likes

Should the FEP-c390 mechanism be used as a mechanism to attach public keys to an actor? Kind of like is done with the publicKey term currently. The two key advantages for me would be:

  • I can attach multiple public keys, e.g. one whose private key is not known to the server, and one whose private key is used by the server

  • One no longer relies on a json-ld term that is marked as deprecated. See here.

If this is the correct mechanism,I would suggest splitting it off into a new FEP, so it can be introduced without a reference to the work in progress [Verifiable Credential Data Integrity].

1 Like

Yes, FEP-c390 mechanism can be used to attach public keys, see did:key.

The intention of this proposal was to cover the case where the private key is not known to server, hence the signature. If key is already known to server, the signature/proof is redundant.

If publicKey is deprecated, perhaps there’s some other term that replaces it, e.g. verificationMethod?

I just realized that my thinking would lead to something that is semantically incorrect. My idea was to suggest adding an RSA public key as an attachment. This key can then be used to encrypt messages to the actor.

This would be abusive as this public key does not serve as an Identity. It serves as a communication tool. Something one should do after the identity is established.

What should one call such an object? EncryptionPublicKey would be one option. It would make the purpose clear and that it should not be used as an identity. In fact, its use will be the EXACT opposite of an identity. Breaking the double usage of keys to sign and encrypt is probably a good idea to make stuff easier to understand.

1 Like

The Identity term (type) is used here in a very broad sense. It is akin to the term “identifier” in DID spec: “globally unique persistent identifier”.

I think end-to-end encryption use case fits the scope of this proposal. We can extend it to include several sub-types, such as EncryptionPublicKey, if there’s a practical benefit in doing that.

1 Like