- Authors: Nikita Khateev
- Status: ACCEPTED
- Since: 2019-05-28
- Status Note: See RFC 0036 for the issue credential part of the same Indy HIPE PR.
- Supersedes: Indy HIPE PR #89; also Credential Exchange 0.1 -- IIW 2019
- Start Date: 2019-01-30
- Tags: feature, protocol, credentials, test-anomaly
Formalization and generalization of existing message formats used for presenting a proof according to existing RFCs about message formats.
We need to define a standard protocol for presenting a proof.
The present proof protocol consists of these messages:
- Propose Proof - Prover to Verifier (optional)
- Request Proof - Verifier to Prover
- Present Proof - Prover to Verifier
In addition, the ack
and problem-report
messages are adopted into the protocol for confirmation and error handling.
This protocol is about the messages to support the presentation of verifiable claims, not about the specifics of particular verifiable presentation mechanisms. This is challenging since at the time of writing this version of the protocol, there is only one supported verifiable presentation mechanism(Hyperledger Indy). DIDComm attachments are deliberately used in messages to try to make this protocol agnostic to the specific verifiable presentation mechanism payloads. Links are provided in the message data element descriptions to details of specific verifiable presentation implementation data structures.
Diagrams in this protocol were made in draw.io. To make changes:
- upload the drawing HTML from this folder to the draw.io site (Import From...GitHub),
- make changes,
- export the picture and HTML to your local copy of this repo, and
- submit a pull request.
An optional message sent by the Prover to the verifier to initiate a proof presentation process, or in response to a request-presentation
message when the Prover wants to propose using a different presentation format. Schema:
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/propose-presentation",
"@id": "<uuid-propose-presentation>",
"comment": "some comment",
"presentation_proposal": <json-ld object>
}
Description of attributes:
comment
-- a field that provides some human readable information about the proposed presentation.presentation_proposal
-- a JSON-LD object that represents the presentation example that Prover wants to provide. It should follow the schema of Presentation Preview;
Request presentation is a message from a verifier to a prover that describes values that need to be revealed and predicates that need to be fulfilled. Schema:
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation",
"@id": "<uuid-request>",
"comment": "some comment",
"request_presentations~attach": [
{
"@id": "libindy-request-presentation-0",
"mime-type": "application/json",
"data": {
"base64": "<bytes for base64>"
}
}
]
}
Description of fields:
comment
-- a field that provides some human readable information about this request for a presentation.request_presentations~attach
-- an array of attachments defining the acceptable formats for the presentation.- For Indy, the attachment contains data from libindy about the presentation request, base64-encoded, as returned from
libindy
. For more information see the Libindy API.
- For Indy, the attachment contains data from libindy about the presentation request, base64-encoded, as returned from
This message is a response to a Presentation Request message and contains signed presentations. Schema:
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation",
"@id": "<uuid-presentation>",
"comment": "some comment",
"presentations~attach": [
{
"@id": "libindy-presentation-0",
"mime-type": "application/json",
"data": {
"base64": "<bytes for base64>"
}
}
]
}
Description of fields:
comment
-- a field that provides some human readable information about this presentation.presentations~attach
-- an array of attachments containing the presentation in the requested format(s).- For Indy, the attachment contains data from libindy that is the presentation, base64-encoded, as returned from
libindy
. For more information see the Libindy API.
- For Indy, the attachment contains data from libindy that is the presentation, base64-encoded, as returned from
This is not a message but an inner object for other messages in this protocol. It is used to construct a preview of the data for the presentation. Its schema follows:
{
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/presentation-preview",
"attributes": [
{
"name": "<attribute_name>",
"cred_def_id": "<cred_def_id>",
"mime-type": "<type>",
"value": "<value>"
},
// more attributes
],
"predicates": [
{
"name": "<attribute_name>",
"cred_def_id": "<cred_def_id>",
"predicate": "<predicate>",
"threshold": <threshold>
},
// more predicates
]
}
The preview identifies attributes and predicates to present.
The mandatory "attributes"
key maps to a list (possibly empty to propose a presentation with no attributes) of specifications, one per attribute. Each such specification proposes its attribute's characteristics for creation within a presentation.
The mandatory "name"
key maps to the name of the attribute.
The optional "cred_def_id"
key maps to the credential definition identifier of the credential with the current attribute. If the key is absent, the preview specifies attribute's posture in the presentation as a self-attested attribute.
The optional mime-type
advises the verifier how to render a binary attribute, to judge its content for applicability before accepting a presentation containing it. Its value parses case-insensitively in keeping with MIME type semantics of RFC 2045. If mime-type
is missing, its value is null.
The optional value
, when present, holds the value of the attribute to reveal in presentation:
- if
mime-type
is missing (null), thenvalue
is a string. In other words, implementations interpret it the same as any other key+value pair in JSON - if
mime-type
is not null, thenvalue
is always a base64-encoded string that represents a binary BLOB, andmime-type
tells how to interpret the BLOB after base64-decoding.
An attribute specification must specify a value
, a cred_def_id
, or both:
- if
value
is present andcred_def_id
is absent, the preview proposes a self-attested attribute; - if
value
andcred_def_id
are both present, the preview proposes verifiable claim to reveal in the presentation; - if
value
is absent andcred_def_id
is present, the preview proposes verifiable claim not to reveal in the presentation.
The mandatory "predicates"
key maps to a list (possibly empty to propose a presentation with no predicates) of predicate specifications, one per predicate. Each such specification proposes its predicate's characteristics for creation within a presentation.
The mandatory "name"
key maps to the name of the attribute germane to the predicate.
The mandatory "cred_def_id"
key maps to the credential definition identifier of the credential with the current attribute.
The mandatory "predicate"
key maps to the predicate operator: "<"
, "<="
, ">="
, ">"
.
The mandatory "threshold"
key maps to the threshold value for the predicate.
The mandatory "filter"
key maps to an object with one or more criteria disjunctively (via "or") applicable to the attribute as a claim.
Filter keys include:
"cred_def_id"
to specify a credential definition identifier"schema_id"
to specify a schema identifier- any other criteria that both the holder and verifier understand in the context of presentation creation.
Negotiation prior to the presentation can be done using the propose-presentation
and request-presentation
messages. A common negotiation use case would be about the data to go into the presentation. For that, the presentation-preview
element is used.
- VCX -- this implementation might not be perfect and needs to be improved, you can gather some info on parameters purpose from it
- A pre-RFC (labeled version 0.1) implementation of the protocol was implemented by a number of groups in the Hyperledger Indy community leading up to IIW28 in April 2019. The protocol can be found here. It was the basis of the IIWBook demo from BC Gov and collaborators.
The presentation preview as proposed above does not allow nesting of predicate logic along the lines of "A and either B or C if D, otherwise A and B", nor cross-credential-definition predicates such as proposing a legal name from either a financial institution or selected government entity.
The presentation preview may be indy-centric, as it assumes the inclusion of at most one credential per credential definition. In addition, it prescribes exactly four predicates and assumes mutual understanding of their semantics (e.g., could ">="
imply a lexicographic order for non-integer values, and if so, where to specify character collation algorithm?).
Finally, the inclusion of non-revocation timestamps may become desirable at the preview stage; the standard as proposed does not accommodate such.
- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?
Similar (but simplified) credential exchange was already implemented in von-anchor.
- We might need some explicit documentation for nested
@type
fields. - There might need to be a way to associate a payment with the present proof protocol.
The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation.
Name / Link | Implementation Notes |
---|---|