FEP-8b32: Object Integrity Proofs¶
| Authors | Status | Type | Date received | Tracking issue | Discussions | Repository |
|---|---|---|---|---|---|---|
| silverpill @silverpill@mitra.social | DRAFT |
implementation | 2022-11-12 | #29 | Discussions | codeberg |
Summary¶
This proposal describes how ActivityPub servers and clients could create self-authenticating activities and objects.
HTTP signatures are often used for authentication during server-to-server interactions. However, this ties authentication to activity delivery, and limits the flexibility of the protocol.
Integrity proofs are sets of attributes that represent digital signatures and parameters required to verify them. These proofs can be added to any activity or object, allowing recipients to verify the identity of the actor and integrity of the data. That decouples authentication from the transport, and enables various protocol improvements such as offline verification and client-side signing.
History¶
Mastodon supports Linked Data signatures since 2017, and a number of other platforms added support for them later. These signatures are similar to integrity proofs, but are based on outdated Linked Data Signatures 1.0 specification, which has been superseded by other standards.
Requirements¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC-2119.
Integrity proofs¶
The proposed authentication mechanism is based on Data Integrity specification.
Proof generation¶
The proof MUST be created according to the Data Integrity specification, section 4.2 Add Proof.
The process of proof generation consists of the following steps:
- Canonicalization is a transformation of a JSON object into the form suitable for hashing, according to some deterministic algorithm.
- Hashing is a process that calculates an identifier for the transformed data using a cryptographic hash function.
- Signature generation is a process that calculates a value that protects the integrity of the input data from modification.
The resulting proof is added to the original JSON object under the key proof.
The list of attributes used in integrity proof is defined in Data Integrity specification, section 2.1 Proofs. The proof type MUST be DataIntegrityProof, as specified in section 3.1 DataIntegrityProof. The value of proofPurpose attribute MUST be assertionMethod.
The value of the verificationMethod attribute of the proof can be an HTTP(S) URI or a DID URL.
The controlled identifier document where the verification method is expressed MUST be an actor object or a DID document that is provably associated with an ActivityPub actor (e.g. using a mechanism described in FEP-c390 or FEP-ef61). The verification method MUST be associated with the assertionMethod property of the controlled identifier document. If controlled identifier document is an actor object, implementers SHOULD use assertionMethod property as described in FEP-521a.
Objects identified using fragment identifiers SHOULD NOT contain integrity proofs.
Objects SHOULD NOT contain more than one integrity proof.
Proof verification¶
Recipients of an object SHOULD perform proof verification if it contains integrity proofs.
Verification process MUST follow the Data Integrity specification, section 4.4 Verify Proof. It starts with the removal of the proof value from the JSON object. Then verification method is retrieved from the controlled identifier document as described in Controlled Identifiers specification, section 3.3 Retrieve Verification Method. Then the object is canonicalized, hashed and signature verification is performed according to the parameters specified in the proof.
The subject of the controlled identifier document where the verification method is expressed MUST be the owner of the signed object, or a DID that is provably associated with that actor (e.g. using a mechanism described in FEP-c390 or FEP-ef61).
If a verifier encounters an integrity proof that uses a verification method that it can't resolve, or uses a cryptosuite that is not supported, or the proof has expired (as indicated by the expires property), the verifier SHOULD ignore the proof and try other authentication methods.
When verifying a delivered activity, the top-level integrity proof MUST take precedence over the HTTP signature if both are present. The HTTP signature MAY be dismissed.
Algorithms¶
Implementers are expected to pursue broad interoperability when choosing algorithms for integrity proofs.
eddsa-jcs-2022 cryptosuite is RECOMMENDED:
- Canonicalization: JCS
- Hashing: SHA-256
- Signatures: EdDSA
Backward compatibility¶
Integrity proofs and linked data signatures can be used together, as they rely on different properties (proof and signature, respectively).
If compatibility with legacy systems is desired, the integrity proof MUST be created and inserted before the generation of the linked data signature.
If both proof and signature are present in a received object, the linked data signature MUST be removed before the verification of the integrity proof.
Security considerations¶
Implementers using integrity proofs as an authentication mechanism are advised to follow the recommendations given in FEP-fe34: Origin-based security model.
Privacy considerations¶
If a private object is signed, its authenticity can be proven if it is distributed beyond the intended recipients. This risk can be mitigated by encrypting private content.
Integrity proofs can be repudiated by rotating the verification method.
Examples¶
Signed object¶
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"id": "https://server.example/objects/1",
"type": "Note",
"attributedTo": "https://server.example/users/alice",
"content": "Hello world",
"proof": {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "https://server.example/users/alice#ed25519-key",
"proofPurpose": "assertionMethod",
"proofValue": "...",
"created": "2023-02-24T23:36:38Z"
}
}
Signed activity¶
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"id": "https://server.example/activities/1",
"type": "Create",
"actor": "https://server.example/users/alice",
"object": {
"id": "https://server.example/objects/1",
"type": "Note",
"attributedTo": "https://server.example/users/alice",
"content": "Hello world"
},
"proof": {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "https://server.example/users/alice#ed25519-key",
"proofPurpose": "assertionMethod",
"proofValue": "...",
"created": "2023-02-24T23:36:38Z"
}
}
Signed activity with embedded signed object¶
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"id": "https://server.example/activities/1",
"type": "Create",
"actor": "https://server.example/users/alice",
"object": {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"id": "https://server.example/objects/1",
"type": "Note",
"attributedTo": "https://server.example/users/alice",
"content": "Hello world",
"proof": {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "https://server.example/users/alice#ed25519-key",
"proofPurpose": "assertionMethod",
"proofValue": "...",
"created": "2023-02-24T23:36:38Z"
}
},
"proof": {
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/data-integrity/v2"
],
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "https://server.example/users/alice#ed25519-key",
"proofPurpose": "assertionMethod",
"proofValue": "...",
"created": "2023-02-24T23:36:38Z"
}
}
Test vectors¶
Implementations¶
- Mitra
- Vervis (generation, verification)
- Streams
- Hubzilla
- Fedify
- apsig
- tootik
- Gush! (commit)
- squidcity
- Mastodon (verification)
Future work¶
Use cases¶
- Forwarding from inbox
- Conversation Containers
- FEP-ef61: Portable Objects
- FEP-ae97: Client-side activity signing
- FEP-1580: Move Actor Objects with a migration Collection
Quantum-resistant cryptosuites¶
This document recommends the eddsa-jcs-2022 cryptosuite, which is not secure against attacks by quantum computers. At the time of writing, the cryptosuites for quantum-resistant integrity proofs are being standardized in Quantum-Resistant Cryptosuites v1.0 specification.
References¶
- Christine Lemmer-Webber, Jessica Tallon, Erin Shepherd, Amy Guy, Evan Prodromou, ActivityPub, 2018
- S. Bradner, Key words for use in RFCs to Indicate Requirement Levels, 1997
- Dave Longley, Manu Sporny, Verifiable Credential Data Integrity 1.0, 2024
- Manu Sporny, Dave Longley, Markus Sabadello, Drummond Reed, Orie Steele, Christopher Allen, Decentralized Identifiers (DIDs) v1.0, 2022
- Dave Longley, Manu Sporny, Markus Sabadello, Drummond Reed, Orie Steele, Christopher Allen, Controlled Identifiers v1.0, 2025
- silverpill, FEP-521a: Representing actor's public keys, 2023
- silverpill, FEP-c390: Identity Proofs, 2022
- silverpill, FEP-ef61: Portable Objects, 2023
- Dave Longley, Manu Sporny, Data Integrity EdDSA Cryptosuites v1.0, 2025
- A. Rundgren, B. Jordan, S. Erdtman, JSON Canonicalization Scheme (JCS), 2020
- silverpill, FEP-fe34: Origin-based security model, 2024
Copyright¶
CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
To the extent possible under law, the authors of this Fediverse Enhancement Proposal have waived all copyright and related or neighboring rights to this work.