FEP-8b32: Object Integrity Proofs

is useful. I also think that the proof format

  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "json-eddsa-2022",
    "created": "2023-02-24T23:36:38Z",
    "verificationMethod": "https://vc.example/issuers/5678#z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2",
    "proofPurpose": "assertionMethod",
    "proofValue": "z4J5StJRP9nWYuCGaxgeCWXmmMJvVtLuVKvYv7z9pkGP1nYpaVk5hUaA8cvS37ncvbKWZgUTaSyGcavnVvb1at9kZ"

looks good and is specified in the context at https://www.w3.org/ns/credentials/v2

My quick search unfortunately, did not reveal a good description of the context. It was introduced in Verifiable Credentials Data Model v2.0 . The good news is that the context allows for adding an “expires” term. This is important as we will want to encourage usage of “time to live” for ActivityPub.


For people preferring to read Python: helge/vc-di-eddsa-python - vc-di-eddsa-python - Codeberg.org

Only the JCS part verifies correctly.

Proposal now recommends jcs-eddsa-2022 cryptosuite: #92 - FEP-8b32: Recommend jcs-eddsa-2022 cryptosuite - fep - Codeberg.org

I’ll implement it too and report my findings.

1 Like

@helge I’m happy to report that my implementation of jcs-eddsa-2022 cryptosuite produces the same signed document as yours!
I’m not deploying it to production though. It would be prudent to wait until workgroup fixes the vc-di-eddsa spec.


jcs-eddsa-2022 description was fixed a couple of days ago (PR). I proceeded with implementation of the algorithm and incorporated it into my software (here is the signing function). However, I’m not sure how to distribute EdDSA keys. The most logical place for them seems to be publicKey property, which can take the form of array where the first item represents RSA key and the second item represents EdDSA key. But servers may expect publicKey to be an object and fail to process an array, making gradual upgrade impossible. So we need to either use some new property (authentication?) or keep RSA as the recommended signature algorithm.

1 Like

One option would be to use the mechanism from fep-4adb and just use a did-key as identity, i.e. have an actor of the form:

  "@context": [
      "xrd": "http://docs.oasis-open.org/ns/xri/xrd-1.0#",
      "aliases": { "@id": "xrd:Alias", "@type": "@id", "@container": "@list"},
  "id": "https://chatty.social/bnm789",
  "preferredUsername": "ben",
  "aliases": [

I don’t see any disadvantages in this approach compared to using a “publicKey” property or similar. I see some advantages in this approach, that’s why the above fep discusses it.

I think this conflicts with the usage of alsoKnownAs property in the Fediverse (things controlled by the same entity). As I pointed out in another thread, there are two possible meanings of the word “alias”, and I think we should not conflate them. If alsoKnowAs is used to describe things controlled by the same entity, aliases should be used to describe different identifiers of the same thing. The definition of xrd:Alias seems to support this:

The <Alias> element does not identify additional resources the XRD is describing, but rather provides additional identifiers for the same resource.

acct:ben@chatty.social and did:key:z6MkekwC6R9bj9ErToB7AiZJfyCSDhaZe1UxhDbCqJrhqpS5 are not additional identifiers of the same resource. The first one points to AP actor, the second one to DID document. Therefore, alsoKnownAs would be more appropriate here.


Or we can flip these properties and use aliases to describe different things controlled by the same entity. This would conflict with the usage of alsoKnownAs property but coincide with the usage of “Alias” in Mastodon documentation.

In the context of FEP-8b32, however, I would prefer to use different property. Maybe even Multikey attachment

let’s not flip the long-established meaning of aliases.

“alias” in mastodon is flavour text for alsoKnownAs and not an actual alias (different id for same thing).

1 Like

As I haven’t given up my hope of introducing Feature tests, this proposal with publicKeyMultibase would like shown in vc-di-eddsa-python/fep-8b32.feature at main - vc-di-eddsa-python - Codeberg.org .

Note, I haven’t updated my vc-di-eddsa implementation to the latest version of the draft yet.


Multikey attachments seem to be a good idea. I’ve quickly written a proposal #105 - WIP: FEP-521a: Representing actor's public keys - fep - Codeberg.org

A few thoughts (not really comments yet):

  • One should explain the distinction between an identifier and a public key. This is not a technical distinction (both can be considered as points on Curve 25519) but a distinction of purpose.
    • An Identifier identifies an actor
    • A Public Key is used by the actor to prove he did something, i.e. by signing it. (Awful sentence)
    • There are more key types see
  • Given their use, one can rotate public keys quite frequently. For example, I could issue a new public key every week with a 2 week expiry. Once the public key is expired, I publish the private key. This means that signatures don’t make it impossible to delete objects.

  • I’m unsure if I like the name “MultiKey”. “Multi” might be taken to mean “multipurpose” instead of being a format. It might be better to specify the use as “SigningKey”. Maybe, one can invent a naming scheme that also covers fep-c390 and uses such as

    • X25519 key exchange, see this
    • What one needs for x3dh / double ratchet
    • Other use cases? Object Capabilities?
1 Like

@codenamedmitri proposed to use properties like authentication, keyAgreement etc to make the purpose of the key clear. I support this.

FEP-521a allows actor to have multiple keys, so you can add a new key without removing the expired one (just mark it as “expired” somehow).

I took it from “EdDSA Cryptosuite v2022” document. There’s a warning about moving it to Data Integrity spec, so we can expect it to become standard. If we replace attachment with authentication, the ambiguity will disappear.

I was thinking of using something like:

    "id": "https://example.com/users/alice#key1",
    "type": "Multikey",
    "controller": "https://example.com/users/alice",
    "expires": "2023-06-24T23:36:38Z",
    "publicKeyMultibase": "z6MkekwC6R9bj9ErToB7AiZJfyCSDhaZe1UxhDbCqJrhqpS5"

to denote a key that will expire. It is then up to the applications to determine if the key is still valid. The one above won’t be in July.

Checking that the key used to sign an activity is not expired, is probably something an application MUST check.

This sounds good. :+1:

1 Like

FEP-521b can not be added to the main FEP repo at the moment, but it is available in my repo: feps/fep-521a.md at main - feps - Codeberg.org

There’s no dedicated topic for it, so I’ll list possible improvements here:

I’ve already implemented FEP-521a and the latest version of FEP-8b32. My actor https://mitra.social/users/silverpill contains both RSA and Ed25519 keys, represented as Multikey verification methods. Outgoing activities are still signed with RSA key, but I can enable jcs-eddsa-2022 to perform federation tests at any time.

@helge Are you planning to move this file to fediverse-features?

I want to add test vectors for FEP-8b32, but I am not sure how to do it. Gherkin syntax looks nice. It is human readable, and it is definitely better than plain JSON files. However, I think it would be better to put test vectors alongside the FEP, and not in a separate repo.

My current plan is to locate all my Gherkin features in that repository. This includes both FEP and ones that test other aspects of the Fediverse.

I have no idea if different repositories for features and docs are a good split. As having a features repository already means that I split code and tests, it doesn’t seem like a big deal to me.

I probably won’t have a firm opinion on what a good structure looks like in the next few weeks.

1 Like

I updated FEP-8b32 (feps/fep-8b32.md at main - feps - Codeberg.org) and the feature file: feps/fep-8b32.feature at main - feps - Codeberg.org. Could you verify it with your implementation?

1 Like

After updating “json-eddsa-2022” to “jcs-eddsa-2022” my tests pass with the new feature.

I just realized Gherkin might not be as well-known as I expected. Have you integrated something like cucumber-rs into Mitra to run this test?

The essential point for me to use Gherkin is that the feature files can be shared across implementations. So in an ideal world, everybody runs the same tests [1]. This will lead to greater interoperability, simply by eliminating one of the points where applications can diverge. I consider Gherkin tests a technical implementation of what @aschrijver calls “common substrate”.

[1]: Various unimportant caveats apply, e.g. every implementation needs to define steps.

1 Like