FEP-c390: Identity Proofs

Why?
The Data Integrity spec provides an example of a signed JSON object: Verifiable Credential Data Integrity 1.0. The @context property is not used there. Also, other attachments are not required to have @context.

If some applications need @context, they can add it. The FEP allows this:

The document MAY contain additional properties.

(The first post in this topic contained an outdated version of this proposal, where additional properties were not allowed. I’ve replaced outdated text with a short summary.)

::facepalms: Nope, you are correct, my mistake :slight_smile:

No @context is needed when using JCS.

@silverpill I looked at this (and made a tentative internal proposal to adopt this) for the Discourse Activity Pub plugin. We didn’t include anything along these lines in Phase 2 of work on that plugin, however it may be possible at some point.

I should be clear that CDCK (Discourse.org) hasn’t endorsed any version of this for their plugin, the Discourse Activity Pub Plugin, yet, however in my own, personal, view (as the current developer of the plugin), I think adding support may be feasible down the line a bit.

Where can I see your implementation? Is there any reference implementation in Ruby? :slight_smile:

Also, is anyone here familiar with the folks involved in Mastodon and/or have a real (i.e. not just speculation) sense of the likelihood of adoption of the same in Mastodon? Mastodon adoption, at least in principle, would obviously be an advantage in advocating for adoption of this in Discourse’s plugin.

3 Likes

Parts of my implementation in Rust can be found here: https://codeberg.org/silverpill/mitra/src/commit/a145afcee174b25e7ec3f517e904ea6c9dd169fe/src/json_signatures/verify.rs. It is still being worked on.

At the moment my ActivityPub server Mitra supports two types of identity proofs:

  • did:key + Minisign signatures. This requires Minisign command line tool.
  • did:pkh + EIP-191 signatures. This type of signature requires an Ethereum cryptocurrency wallet.

These kinds of proofs are not suitable for an average user. Moreover, the cryptosuites being used are non-standard, there are no official specifications for them. I found a way to generate jcs-eddsa-2022 proof using Minisign, but haven’t implemented it yet. Still, it requires a command line tool, so it is only suitable for power users.

Probably not. However, there’s now an implementation of JCS in Ruby: GitHub - dryruby/json-canonicalization: An implementation of the JSON Canonicalization Scheme for Ruby (it is required for jcs-eddsa-2022).

I don’t think Mastodon would adopt it until UX issues are resolved. I see 3 possible ways to improve the situation:

  • Use did:key and develop a browser extension that will manage private keys.
  • Use did:key but do not require any browser extensions or other apps. Store encrypted private key on a server, decrypt on a client side, ask user to make a backup (afaik matrix is doing something similar).
  • Use did:web. Keys are managed by 3rd party.
3 Likes

#137 - FEP-c390: Update proposal - fep - Codeberg.org - added test vectors.

I have a “crazy idea”. Consider the following type of identity proof:

  {
      "type": "VerifiableIdentityStatement",
      "subject": "acct:bob@abel.example",
      "alsoKnownAs": "https://banach.example/users/bob"
  }

So this corresponds to @bob@abel.example having migrated to @bob@banach.example. If abel updates the webfinger entry to return the actor on banach, it is clear that this would be a two way verification.

I think proof is supposed to represent some kind of cryptographic signature. If you don’t need a signature, then alsoKnownAs property is probably all you need

2 Likes

+1 to what silverpill said.

I’ve updated the post by removing proof. It’s probably less confusing this way than me just saying it’s good to not use the proof value. I’m also aware that this is kind of out of scope of FEP-c390 as subject is required to be a did there.

Anyway, thinking about this, I have one more naming comment: Would VerifiableIdentifier be a better name for the type? The advantage is that subject is an identifier that can be verified, either through the proof, or as in the case I wrote above by making a webfinger lookup.

1 Like

I’m not quite happy with VerifiableIdentityStatement type, but I don’t think VerifiableIdentifier is better. FEP-c390 identity proof establishes a link between the subject and the actor specified by alsoKnownAs property. We’re not verifying the identifier, but a relationship between two identifiers. For this very reason I discarded the Identity type, which was used in earlier FEP-c390 drafts.

VC workgroup changed the name of cryptosuite from jcs-eddsa-2022 to eddsa-jcs-2022. The FEP has been updated accordingly. I also added some minor clarifications and implementation notes.

@helge I just discovered that subject property is already defined in ActivityStreams vocabulary: Activity Vocabulary, so we probably should’t re-define it?

ActivityStreams vocabulary also contains Relationship type:

Describes a relationship between two individuals

Perhaps VerifiableIdentityStatement should be defined as a sub-type of Relationship? In some sense it is a relationship: not between individuals though, but between different IDs belonging to the same individual.

To align this FEP with FEP-888d, I’m going to update c390/context.jsonld file with:

{
  "@context": {
    "VerifiableIdentityStatement": "https://w3id.org/fep/c390/VerifiableIdentityStatement",
    "subject": {
      "@id": "https://www.w3.org/ns/activitystreams#subject",
      "@type": "@id"
    },
    "alsoKnownAs": {
      "@id": "https://www.w3.org/ns/activitystreams#alsoKnownAs",
      "@type": "@id"
    }
  }
}

@trwnh Is it correct context document?

There is a high chance that feature file is incorrect because context injection is required.

This operation is not present in eddsa-jcs-2022 cryptosuite description, but only briefly mentioned in Data Integrity spec.

Tracking issue: Clarify when and how to perform context injection · Issue #231 · w3c/vc-data-integrity · GitHub

Update: #234 - FEP-c390: Update proposal - fediverse/fep - Codeberg.org

Notable changes:

  • Using the subject property from the ActivityStreams vocabulary instead of a custom property.
  • New context.jsonld for FEP-888d (ping @trwnh).
  • Added a warning about eddsa-jcs-2022 stability and removed the .feature file because it was not correct (at the time of writing the context injection issue remains unresolved).
3 Likes

looks fine, only thing i’d consider is adding a formal definition for VerifiableIdentityStatement either in a sidecar asset (as the IRI implies) or in the FEP itself (and in such case i’d consider using a fragment id instead of a subpath)

there is an example in 888d of SomeType being defined in fep/fep/888d/SomeType at main - fediverse/fep - Codeberg.org a la http://schema.org/SomeType style definition pages (although i left it as a plaintext file because i didn’t want to bother working out HTML conneg just yet)

2 Likes

Formal definition added: fep/fep/c390/VerifiableIdentityStatement at c927cec6e7a61f045ebf9d6a30fb191bdd0b3092 - fediverse/fep - Codeberg.org

1 Like

I’m currently thinking through what the first version of this might look like in the Discourse ActivityPub plugin. The initial goal for the end-user experience here is

Allow a Discourse user to claim another Discourse user associated with an ActivityPub Actor

This is what happens in the plugin currently

  1. Individual A (i.e. the actual person) uses User A to make a post on Discourse A.
  2. Post A is published as Object A (i.e. Note or Article) attributed to Actor A, associated with User A on Discourse A.
  3. Discourse B receives Object A, and creates User B for Actor A and Post B for Object A.

To achieve the initial goal the following will need to happen

  1. Individual A also controls User C on Discourse B.
  2. User C proves ownership of Actor A by Individual A authenticating User A on Discourse A as User C.

I appreciate that the initial goal can be achieved using standard authentication mechanisms (i.e without identity proofs). What I’m interested in is potentially laying the groundwork for supporting identify verification in a non-Discourse specific way, i.e. so that Individual A could also claim Actor A on other services. This is what I’m currently thinking might be possible to lay that groundwork

  • Individual A enters the handle of Actor A in the UI
  • The plugin retrieves Actor A from Discourse A via Webfinger.
  • Actor A includes a VerifiableIdentityStatement as an attachment with
  • Discourse B presents Actor A’s VerifiableIdentityStatement to Discourse B using the service endpoint.
  • Discourse A verifies the presentation.
  • if the presentation is verified, Discourse A asks Individual A to authenticate as User A.
  • Upon successful verification and authentication, Discourse A returns a verified claim to Discourse B.
  • Upon receipt of a verified claim, Discourse B allows User C to claim User B.

A version of that could potentially achieve my immediate goal, while also allowing for FEP-c390 support. I appreciate this initial version is imperfect and not decentralized . The goal is not to achieve perfection, but to achieve the immediate goal while building the right structure.

Any suggestions are welcome.

3 Likes

What claiming of a user means for an individual? Is it just a pointer to another account, or you’re planning to add more functionality that will depend on this mechanism?

Top-level alsoKnownAs is another way to link ActivityPub actors. It is used for migrating account’s followers from one server to another in micro-blogging apps and it is easier to implement than FEP-c390

If the long-term goal is full data portability, then FEP-ef61 could help.