§ AnonCreds Specification
Specification Status: v1.0 Draft
Latest Draft:
https://github.com/hyperledger/anoncreds-spec
Editors:
- Stephen Curran
- Artur Philipp - Technische Universität Berlin, IDunion
- Hakan Yildiz - Technische Universität Berlin, IDunion
- Sam Curren
- Victor Martinez Jurado
- Participate:
- GitHub repo
- Commit history
- Discord
§ Abstract
The AnonCreds (Anonymous Credentials) specification is based on the open source verifiable credential implementation of AnonCreds that has been in use since 2017, initially as part of the Hyperledger Indy open source project and now in the Hyperledger AnonCreds project. The extensive use of AnonCreds around the world has made it a de facto standard for ZKP-based verifiable credentials, and this specification is the formalization of that implementation.
For more details on what AnonCreds are and how they work you can refer to the Anonymous credentials with type-3 revocation by Dmitry Khovratovisch, Michael Lodder and Cam Parra which is the compiled pdf from their official TeX document published under CC4.0 license.
§ Status of This Memo
This is a proposal for version v1.0 of AnonCreds which aims at AnonCreds being ledger agnostic.
This document is a product of the AnonCreds Working Group. It represents the consensus of the AnonCreds community. The proposal for v1.0 has partly been worked out at the RWOT2022 event in the Hague, Netherlands.
Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at https://github.com/hyperledger/anoncreds-spec.
§ Copyright Notice
This specifications is subject to the Community Specification License 1.0 available at https://github.com/CommunitySpecification/1.0.
If source code is included in the specification, that code is subject to the Apache 2.0 license unless otherwise marked. In the case of any conflict or confusion within this specification between the Community Specification License and the designated source code license, the terms of the Community Specification License shall apply.
§ Introduction
AnonCreds ZKP verifiable credentials provide capabilities that many see as important for digital identity use cases in particular, and verifiable data in general. These features include:
- A full implementation of the Layer 3 verifiable credential “Trust Triangle” of the Trust over IP Model.
- Complete flows for issuing verifiable credentials (Issuer to Holder), and requesting, generating and verifying presentations of verifiable claims (Holder to Verifier).
- Fully defined data models for all of the objects in the flows, including verifiable credentials, presentation requests and presentations sourced from multiple credentials.
- Fully defined applications of cryptographic primitives.
- The use of Zero Knowledge Proofs (ZKPs) in the verifiable presentation process to enhance the privacy protections available to the holder in presenting data to verifiers, including:
- Blinding issuer signatures to prevent correlation based on those signatures.
- The use of unrevealed identifiers for holder binding to prevent correlation based on such identifiers.
- The use of predicate proofs to reduce the sharing of PII and potentially correlating data, especially dates (birth, credential issuance/expiry, etc.).
- A revocation scheme that proves a presentation is based on credentials that have not been revoked by the issuers without revealing correlatable revocation identifiers.
This version (v1.0) removes any dependence on Hyperledger Indy by removing any requirements related to the storage of the objects used in AnonCreds, whether they be stored remotely on a “verifiable data registry” (including Hyperledger Indy) or in local secure storage.
The following diagram and explanation below give a high-level overview of all AnonCreds Data objects, their relations and the owner respectively receiver of each of the data objects.
AnonCreds require a Verifiable Data Registry (VDR). A VDR (box in green) is a public registry (often a ledger) used for storing some of the AnonCreds data objects.
Schemas are public and reusable templates, which define the attributes of issued AnonCreds credentials and can be written (e.g. by an Issuer) to the VDR.
Based on a Schema, arbitrary Issuers (box in yellow) can create a Credential Definition (Credential Definition) which references the Schema. A Credential Definition enables Issuers to issue AnonCreds Credentials to Holders and enables Verifiers (box in red) to verify Credentials issued to and presented by a Holder. A Credential Definition consists of two pieces of information: First, the Private Credential Definition includes the private signing keys of the Issuer for signing and issuing AnonCreds Credentials to holders and is kept private by the Issuer. Second, the Public Credential Definition includes the public keys of the Issuer, has to be stored on a VDR and is used by holders and arbitrary Verifiers in order to verify AnonCreds Credentials issued to and presented by Holders.
Each Holder (box in blue) has a link secret, which enables Credential to Holder binding: Whenever a Credential is issued to a Holder by an Issuer, the Holder sends a blinded version of the link secret to the Issuer before the credential is issued to the Holder. The blinded version of the link secret gets then signed along with the other attributes within the AnonCreds Credential by the Issuer and sent to the Holder. Since the Holder uses a blinded version of the same link secret for every Credential that is issued to the Holder, the Holder can proof the affiliation of multiple Credentials at presentation time.
Holders never present the raw signed credential data they received from Issuers to Verifiers for verification purposes. Instead a Verifiable Presentation is created by the Holder and sent to the Verifier. A Verifiable Presentation is a derivation of an AnonCreds Credential which allows a Holder to proof the correctness of the revealed credential data, without revealing the original raw credential signature(s). Verifiers process Verifiable Presentations for verification of credential data.
AnonCreds allows the revocation of Credentials issued to Holders by Issuers. In case revocation is required, at least one (Revocation Registry Definition), which references the associated Public Credential Definition, has to be stored to the VDR by the Issuer in addition to the Public Credential Definition. A Revocation Registry Definition can have Revocation Status Lists. When one or more credentials have to be revoked, the Issuer stores a Revocation Status List with the updated status of the credentials in question to the VDR. Holder use these additional pieces of information in order to generate a Non-Revocation Proof. A Non-Revocation Proof proves to a Verifier, that the credential the Holder presented to the Verifier, has not been revoked. Verifiers use the information provided by a Revocation Registry Definition and associated Revocation Status Lists to verify the Holder`s Non-Revocation Proof. A Tails File supports the revocation mechanism. Each Revocation Registry Definition requires exactly one Tails File.
§ Requirements, Notation and Conventions
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
a || b
: Denotes the concatenation of octet strings a and b.
I \ J
: For sets I and J, denotes the difference of the two sets i.e., all the elements of I that do not appear in J, in the same order as they were in I.
X[a..b]
: Denotes a slice of the array X containing all elements from and including the value at index a until and including the value at index b. Note when this syntax is applied to an octet string, each element in the array X is assumed to be a single byte.
range(a, b)
: For integers a and b, with a <= b, denotes the ascending ordered list of all integers between a and b inclusive (i.e., the integers “i” such that a <= i <= b).
length(input)
: Takes as input either an array or an octet string. If the input is an array, returns the number of elements of the array. If the input is an octet string, returns the number of bytes of the inputted octet string.
H(...)
: Any hash function.
Terms specific to pairing-friendly elliptic curves are:
E1, E2
: elliptic curve groups defined over finite fields. This document assumes that E1 has a more compact representation than E2, i.e., because E1 is defined over a smaller field than E2.
G1, G2
: subgroups of E1 and E2 (respectively) having prime order r.
GT
: a subgroup, of prime order r, of the multiplicative group of a field extension.
e
: G1 x G2 -> GT: a non-degenerate bilinear map.
r
: The prime order of the G1 and G2 subgroups.
P1, P2
: points on G1 and G2 respectively. For a pairing-friendly curve, this document denotes operations in E1 and E2 in additive notation, i.e., P + Q denotes point addition and x * P denotes scalar multiplication. Operations in GT are written in multiplicative notation, i.e., a * b is field multiplication.
§ Terminology
- Blinding factor
-
Blinding factor is a 3152 bit number generated randomly that is used to blind the
link_secret
and non-disclosed attributes during the issuance of credentials. - claim
-
A claim is a part of digital identity related to a subject. A claim can be attested by the identity subject itself, or it can be asserted by another entity.
- Credential Key Correctness Proof
-
This is produced during the creation of the Credential Definition and is included in the Credential Offer so that the holder can verify that the Public Credential Definition used in the blinding process belongs to the issuer.
- Signature Correctness Proof
-
A ZKP based proof to show that a signature to a message is valid, without revealing the message or signature.
- Blinded Secrets Correctness Proof
-
A ZKP based proof to show that some blinded secret was produced correctly from an unblinded secret without exposing the secret to anyone.
- credential
-
A credential is a set of claims about an identity subject. A verifiable credential is a tamper-proof credential whose authorship is cryptographically verifiable. An anonymous credential, also known as AnonCreds, is a verifiable credential that has privacy-preserving properties to enable data minimization and correlation resistance.
- Credential Definition
-
A Credential Definition (also known as CRED_DEF or CLAIM_DEF) contains data required for credential issuance (used by the issuer) as well as credential validation data (used by the holder and the verifier). A Credential Definition is generated by the issuer before credential issuance and consists of two distinct but strongly related parts, the Public Credential Definition and Private Credential Definition.
-
A Public Credential Definition part of a Credential Definition is a public object (e.g. on a ledger), that references a Schema, references a DID of the issuer and can be written to the ledger by any issuer who intends to issue credentials based on that specific Schema and has the proper permissions in doing so. A Public Credential Definition has to be accessible to all participants (issuers, holders, and verifiers). A Schema is in a 1:n relation with Public Credential Definition, meaning there can be many Public Credential Definition related to the same Schema while a Credential Definition can only reference one single Schema. Whenever an AnonCreds credential is issued, it is based on a Credential Definition. That means, the issued credential can only have the attributes listed in the Schema, which is referenced by the Public Credential Definition part. An exception to this is the blinded and signed link secret, an attribute which is part of every AnonCred credential. The issuer`s public keys for verifying the attributes (one key for one attribute) are within the Public Credential Definition, which allows validation of the credentials by verifiers.
-
The Private Credential Definition part of a Credential Definition is stored on the issuer's side and is an object that contains the issuer`s private keys for signing the attributes (one key for one attribute) when issuing an AnonCreds Credential. These private keys are used to create signature proofs for the issued anonymous credentials, which then can be validated in a derived form by a verifier by using the published public keys of the Public Credential Definition part. A Private Credential Definition never leaves the Issuer's domain and is stored securely.
-
Revokable Verifiable Credentials require (besides) a Credential Definition also a REV_REG_DEF.
- Credential Offer
-
A credential offer is an offering from an issuer towards a holder to issue a credential. The credential offer contains the details about the claims the issuer intends to issue to the holder. A holder can reply to the issuer with a Credential Request. A credential offer also includes a nonce and a Credential Key Correctness Proof.
- Credential Request
-
A credential request is a request from an holder towards a issuer to get a credential issued by the issuer. The credential request references a preceding Credential offer and defines the claims the holder wants to get issued. A credential request also includes a nonce.
- DID
-
A Decentralized Identifier (DID), defined by the W3C DID Core Specification, is a type of identifier that enables verifiable, decentralized digital identity. A DID refers to any subject (e.g., a person, organization, thing, data model, abstract entity, etc.) as determined by the controller of the DID. DIDs are not used in AnonCreds itself but there must be an DID-based, enforced relationship between the schema and issuers and the AnonCreds objects they publish. This is outlined in a note in this section of this specification.
- holder
-
A holder, also known as an identity holder, is an entity that is in possession of a credential. In many use cases, the holder is also the identity subject. A holder can interact with an issuer to obtain anonymous credentials. It can also derive information from anonymous credentials that can be presented to a verifier to gain access to goods and services.
- issuer
-
An issuer is one of the three entities that interact with each other within the domain of digital identities. It can assert claims about a subject in the form of a tamper-proof credential whose origins are cryptographically verifiable.
- Issuer Identifier
-
An issuer identifier is a unique identifier for an issuer. It is used to identify the issuer of AnonCreds objects published to a Verifiable Data Registry . See Issuer Identifiers for details.
- link secret
-
One of the most significant differences between the AnonCreds and W3C Verifiable Credentials is how a credential is bound to the holder. With the Verifiable Credential, the holder binding happens without additional interactions between the holder and issuer. However, this approach comes with a lack of privacy for the holder. The correlatability of credentials due to the necessity of revealing a persistent identifier related to the holder is one such privacy issue.
-
AnonCreds are bound to the holder with a non-correlatable secret only known to the holder itself called a link secret*. Instead of a persistent identifier, the link secret as a blind attribute is sent to the issuer during credential issuance. The issuer signs every claim (including the blinded link secret) individually, enabling selective disclosure (see below). It means the issuer does not know the exact value of the link secret, and the holder can prove the ownership of credentials to a verifier without disclosing a persistent identifier.
-
*) The link secret is known as master secret in the Hyperledger Indy source code. The term “master secret” is deprecated in AnonCreds.
- nonce
-
A nonce is an arbitrary unique number that is used to ensure secure communications. Within AnonCreds, nonces are used during credential issuance e.g. for binding a Credential Request to a Credential Offer.
- predicates
-
A predicate is a boolean assertion about the value of a claim without disclosing the value itself. In contrast to any signature suite and algorithm implemented according to the W3C Verifiable Credentials, predicates are fully supported by AnonCreds.
- NRP
-
TODO Non Revocation Proof
- Revocation Registry Definition
-
A Revocation Registry Definition object contains information required for verifiers in order to enable them to verify whether a revokable verifiable credential has been revoked by the issuer since issuance.
-
Revocation Registry Definitions are only needed for revokable verifiable credentials and are most commonly written to a public location (e.g. an indy ledger) by the owner of a Credential Definition immediatly after the Credential Definition has been written. They can be read from a Hyperledger Indy Node by any client and are updated in case of the revocation of a credential, which is based on the used Credential Definition.
-
Further details about Hyperledger Indy’s revocation process can be found here.
- Revocation Status List
-
A Revocation Status List object marks the current status (“revoked” or “not revoked”) of all credentials in a Revocation Registry Definition. A Revocation Status List is written by the owner of a Revocation Registry Definition, respectively the issuer of the credential(s) based on a Credential Definition and its Revocation Registry Definition.
- Schema
-
A Schema object is a template that defines a set of attributes (also known as attribute names or claims) which are going to be used by issuers for issuance of Verifiable Credentials within a Hyperledger Indy network. Schemas have a name, version and can be written to the ledger by any entity with proper permissions. Schemas can be read from a Hyperledger Indy Node by any client.
-
In Hyperledger Indy, Credentials are based on a Credential Definition. Therefore Credential Definitions reference a Schema in order to define which attribute(names) will be used within the Credential Definition.
- Schema publisher
-
A Schema publisher is an entity that creates a Schema to the ledger. It can be the issuer, but it can also be another entity that creates a Schema that can be used by many issuers to create Credential Definitions (see below).
- selective disclosure
-
Selective disclosure is the ability to disclose partial information from an issued credential by disclosing only a subset of claims.
- subject
-
A subject, also known as an identity subject, is the entity about whom claims are made.
- Tails File
-
TODO
- Verifiable Data Registry
-
DIDs and DID documents have to be stored on some kind of system, which is available (to the public, in most cases). Such a system can be a distributed ledger, a (decentralized) file system, database and others. Such an anchor for [[ref: DID]s] and DID documents is called Verifiable Data Registry.
-
In the case of Hyperledger Indy a distributed ledger is used as Verifiable Data Registry. Besides DIDs and DID documents an instance of a Hyperledger Indy network stores additional data on the ledger, which is required for issuance (e.g. Schema and Credential Definition), verification (e.g. Revocation Registry Definition)) and revocation (e.g Revocation Status List) of credentials.
- Verifiable Presentation
-
Usually, a VP is a collection of claims obtained from one or more VCs with added proof. Contrary to VCs, VPs are built so that the owner of the data (holder) is cryptographically verifiable. More often than not, the data included in a presentation is just about the subject of a VC, although that’s not mandatory. The AnonCreds enable the holder to prove it holds a claim from a VC without revealing the VC itself. The value in the VP has to be derived in such a way that guarantees (in the form of a cryptographic assertion) any given verifier that they can trust the claimed assertion.
- Verifier
-
A verifier is an entity that validates identity information from a holder to grant access to goods and services.
- Witness Delta
-
The witness delta is an update by the issuer of the list of revoked credentials at the time an updated accumulator is published with a Revocation Status List. The delta tells holders generating a Non-Revocation Proof (NRP) how to adjust their witness (referencing other indexes in the public tails file) to bring it back into harmony with the current value of the accumulator, such that the updated witness times the private factor of the credential once again equals the accumulator value.
- zero-knowledge proofs
-
In cryptography, the zero-knowledge proof is a method by which an entity can prove that they know a certain value without disclosing the value itself. Zero-knowledge proofs can enable holders to:
-
_ Combine multiple credentials into a single proof to present to a verifier without revealing any correlatable identifier.
-
_ selective disclosure (see below) and disclose only necessary claims to a verifier.
-
* use predicates (see below) for enclosing logical expressions, such as the holder being older than 18 without disclosing the value.
-
AnonCreds are capable of all three features mentioned above.
Question: Should the items that are AnonCreds data models be included in this?
§ AnonCreds Setup Data Flow
The following sequence diagram summarizes the setup operations performed by a Schema Publisher, the Issuer (one required and one optional) in preparing to issue an AnonCred credential based on provided Schema, and the one setup operation performed by each Holder. On successfully completing the operations, the Issuer is able to issue credentials based on the given Schema to the Holder. The subsections below the diagram detail each of these operations.
Data Registry participant SP as Schema Publisher participant I as Issuer participant H as Holder Note over L, H: Schema Publisher: Publish Schema SP ->> L: Publish Schema (Schema) L ->> I: Schema ID,
Schema Transaction ID Note over L, H: Issuer: Create, Store and Publish CredDef I ->> I: create_and_store_credential_def
(Schema, tag, support_revocation) Note right of I: store public /
private keys and
correctness proof I ->> L: Publish CredDef (CredDef) Note over L, H: Issuer: Create, Store and Publish Revocation Registry (Optional) I ->> I: create_and_store_revoc_reg (intCredDef) Note right of I: get keys Note right of I: store revoc_reg_def,
revoc_reg_accum,
priv_key,
tails_generator I ->> L: Publish RevReg
(revoc_reg_id,
revoc_reg_def_json,
revoc_reg_entry_json) Note over L, H: Holder: Create and Store Link Secret H ->> H: anoncreds_prover_create_link_secret H ->> H: store link secret rect rgb(191, 223, 255) Note left of H: 💡The "Verifier" role is
omitted in this
diagram, since
it is not required
for the setup end
Those with a knowledge of DIDs might expect that in the flow above, the first step would be for the issuer to publish a DID. However, in AnonCreds, DIDs are not used in the processing of credentials, and notably, the public keys used in AnonCreds signatures come not from DIDs, but rather from Credential Definition objects. DIDs may be used to identify the entity publishing the objects that are then used in the processing of credentials – the Schema, Credential Definition, Revocation Registry Definition and Revocation Status List objects. There is an enforced relationship between an identifier (such as a DID) for the entity publishing the AnonCred objects, and the objects themselves. For example, in the Hyperledger Indy implementation of AnonCreds, for a credential issuer to publish a Credential Definition on an instance of Indy it must have a DID on that instance, and it must use that DID to sign the transaction to write the Credential Definition.
The DID of the publisher of an AnonCreds object MUST be identifiable from the published object and enforcement of the relationship between the DID and the object must be enforced. For example, in the Hyperledger Indy implementation of AnonCreds, the DID of the object publisher is part of the identifier of the object – given the identifier for the AnonCreds object (e.g. one found in proving a verifiable credential), the DID of the publisher can be found. Further, the Hyperledger Indy ledger enforces, and makes available for verification, the requirement that the writing of the AnonCreds object must be signed by the DID that is writing the object.
If a DID-based messaging protocol, such as DIDComm is used between the AnonCreds participants (the issuer, holder and verifier) the use of DIDs for messaging is independent of their use (or not) in the publishing AnonCreds objects. Such DIDs are used to facilitate secure messaging between the participants to enable the issuing of credentials and the presentation of proofs.
§ Schema Publisher: Publish Schema Object
Each type of AnonCred credential is based on a Schema published to a Verifiable
Data Registry (VDR), an instance of Hyperledger Indy in this version of
AnonCreds. The Schema is defined and published by the Schema Publisher. Any issuer
who can reference the Schema (including the Schema Publisher) MAY issue
credentials of that type by creating and publishing a Credential Definition based on the
Schema. This part of the specification covers the operation to create and
publish a Schema. The flow of operations to publish a Schema is illustrated in
the Schema Publisher: Publish Schema
section of the AnonCreds Setup Data
Flow sequence diagram.
The Schema is a JSON structure that can be manually constructed, containing the list of attributes (claims) that will be included in each AnonCreds credential of this type. The following is an example Schema:
{
"issuerId": "https://example.org/issuers/74acabe2-0edc-415e-ad3d-c259bac04c15",
"name": "Example schema",
"version": "0.0.1",
"attrNames": ["name", "age", "vmax"]
}
issuerId
- the Issuer Identifier of the schema. MUST adhere to Issuer Identifiers rules.name
(string) - the name of the schemaversion
(string) - the schema version as a documentation string that it’s not validated. The format is up to each implementor or publisher. For example, Indy uses Semantic VersioningattrNames
(str[]) - an array of strings with each string being the name of an attribute of the schema
Once constructed, the Schema is published to a Verifiable Data Registry
(VDR) using the Schema Publishers selected AnonCreds Objects Method.
For example, see this
Schema that is published on
the Sovrin MainNet instance of Hyperledger Indy. The schemaId
for that object
is: Y6LRXGU3ZCpm7yzjVRSaGu:2:BasicIdentity:1.0.0
.
The identifier for the schema is dependent on where the Schema is published and the AnonCreds method used.
§ Issuer Create and Publish Credential Definition Object
Each Issuer of credentials of a given type (e.g. based on a specific Schema) must
create a Credential Definition for that credential type. The flow of operations to create and
publish a Credential Definition is illustrated in the Issuer: Create, Store and Publish Credential Definition
section of the AnonCreds Setup Data Flow sequence
diagram.
In AnonCreds, the Credential Definition and Credential Definition identifier include the following elements.
- A link to the Issuer of the credentials via the DID used to publish the Credential Definition.
- A link to the Schema upon which the Credential Definition is based (the credential type).
- A set of public/private key pairs, one per attribute (claim) in the credential. The private keys will later be used to sign the claims when credentials to be issued are created.
- Other information necessary for the cryptographic signing of credentials.
- Information necessary for the revocation of credentials, if revocation is to be enabled by the Issuer for this type of credential.
We’ll initially cover the generation and data for a Credential Definition created without the option of revoking credentials. In the succeeding section, we describe the additions to the generation process and data structures when credential revocation is enabled for a given Credential Definition.
§ Retrieving the Schema Object
Prior to creating a Credential Definition, the Issuer must get an instance of the Schema upon which the Credential Definition will be created. If the Issuer is also the Schema Publisher, they will already have the Schema. If not, the Issuer must request that information from the VDR on which the Schema is published. In some AnonCreds Objects there is a requirement that the Schema and Credential Definition must be on the same VDR.
§ Generating a Credential Definition Without Revocation Support
The Credential Definition is a JSON structure that is generated using cryptographic primitives (described below) given the following inputs.
- A Schema and identifier for the schema for the credential type.
- A
tag
, an arbitrary string defined by the Issuer, enabling an Issuer to create multiple Credential Definitions for the same Schema. - An optional flag
support_revocation
(defaultfalse
) which if true generates some additional data in the Credential Definition to enable credential revocation. The additional data generated when this flag istrue
is covered in the next section of this document.
The operation produces two objects, as follows.
- The Private Credential Definition, an internally managed object that includes the private keys generated for the Credential Definition and stored securely by the issuer.
- The Credential Definition, that includes the public keys generated for the Credential Definition, returned to the calling function and then published on a VDR (currently Hyperledger Indy).
The following describes the process for generating the Credential Definition and Private Credential Definition data.
- Build a credential schema using the schema definition.
- Build a non-credential schema that contains the single attribute
master_secret
, that will be used to hold the holder’s blinded link secret. The non-credential schema attribute is included in all AnonCreds verifiable credentials. - Generate random 1536-bit primes , , such that and are primes too. , , and , are Sophie Germain and Safe primes.
- Compute .
- Compute random in the range of safe primes, using the non-credential and credential schema attributes.
- Compute random quadratic residue modulo (select a random number from to , and square it ).
- Compute , and
- Credential Definition public key is and the private key is
Here is the rust implementation of the above process.
The Private Credential Definition produced by the generation process has the following format:
{
"p_key": {
"p": "123...782",
"q": "234...456"
},
"r_key": null
}
The Credential Definition has the following format (based on this example Credential Definition on the Sovrin MainNet):
{
"issuerId": "did:indy:sovrin:SGrjRL82Y9ZZbzhUDXokvQ",
"schemaId": "did:indy:sovrin:SGrjRL82Y9ZZbzhUDXokvQ/anoncreds/v0/SCHEMA/MemberPass/1.0",
"type": "CL",
"tag": "latest",
"value": {
"primary": {
"n": "779...397",
"r": {
"birthdate": "294...298",
"birthlocation": "533...284",
"citizenship": "894...102",
"expiry_date": "650...011",
"facephoto": "870...274",
"firstname": "656...226",
"link_secret": "521...922",
"name": "410...200",
"uuid": "226...757"
},
"rctxt": "774...977",
"s": "750..893",
"z": "632...005"
}
}
}
The Credential Definition contains a cryptographic public key that can be used to
verify CL-RSA signatures over a block of L
messages m1,m2,...,mL
. The Credential Definition contains a public key fragment for each message being signed by
signatures generated with the respective private key. The length of the block of
messages, L
, being signed is defined by referencing a specific Schema with a
certain number of attributes, A = a1,a2,..
and setting L
to A+1
. The
additional message being signed as part of a credential is for a link_secret
(called the link_secret everywhere except in the existing open source
code and data models) attribute which is included in all credentials. This value
is blindly contributed to the credential during issuance and used to bind the
issued credential to the entity to which it was issued.
All integers within the above Credential Definition example json are shown with ellipses (e.g. 123...789
). They are 2048-bit integers represented as 617
decimal digits. These integers belong to an RSA-2048 group characterised by the n
defined in the Credential Definition.
issuerId
- the Issuer Identifier of the credential definition. MUST adhere to Issuer Identifiers rules.schemaId
- (string) The identifier of the Schema on which the Credential Definition is based. The format of the identifier is dependent on the AnonCreds Objects Method used in publishing the Schema.type
- (string) The signature type of the Credential Definition. For this version of AnonCreds the value is alwaysCL
.tag
(string) - the tag value passed in by the Issuer to an AnonCred’s Credential Definition create and store implementation.value
- (object) an Ursa native object with theprimary
andrevocation
fields.primary
is the data used for generating credentials.n
is a safe RSA-2048 number. A large semiprime number such thatn = p.q
, wherep
andq
are safe primes. A safe primep
is a prime number such thatp = 2p'+ 1
, wherep'
is also a prime. Note:p
andq
are the private key for the public CL-RSA key this Credential Definition represents.r
is an object that defines a CL-RSA public key fragment for each attribute in the credential. Each fragment is a large number generated by computings^{xri}
wherexri
is a randomly selected integer between 2 andp'q'-1
.master_secret
(also known as link secret, but kept as master_secret for backwards compatibility) is the name of an attribute that can be found in each Credential Definition. The associated private key is used for signing a blinded value given by the Holder to the Issuer during credential issuance, binding the credential to the Holder.- The rest of the attributes in the list are those defined in the Schema.
- The attribute names are normalized (lower case, spaces removed) and listed in the Credential Definition in alphabetical order.
rctxt
is equal tos^(xrctxt)
, wherexrctxt
is a randomly selected integer between2
andp'q'-1
. (I believe this is used for the commitment scheme, allowing entities to blindly contribute values to credentials.)s
is a randomly selected quadratic residue ofn
. This makes up part of the CL-RSA public key, independent of the message blocks being signed.z
is equal tos^(xz)
, wherexz
is a randomly selected integer between2
andp'q'-1
. This makes up part of the CL-RSA public key, independent of the message blocks being signed.
The identifier for the Credential Definition is dependent on where the Credential Definition is published and the AnonCreds method used.
§ Generating a Credential Definition With Revocation Support
The issuer enables the ability to revoke credentials produced from a Credential Definition by
passing to the Credential Definition generation process the flag support_revocation
as
true
. When revocation is to enabled for a Credential Definition, additional data related to
revocation is generated and added to the Credential Definition JSON objects defined above. In
the following the additional steps in the Credential Definition generation process to enable
revocation are described, along with the additional data produced in that
process.
The following describes the process for generating the revocation portion of the Credential Definition data. This process extends the process for generating a Credential Definition in the previous section of this document.
The revocation scheme uses a pairing-based dynamic accumulator based on the CKS scheme.
Pairing cryptography makes use of two pairing-friendly elliptic curve groups (G1, G2) with a known, computable pairing function e(G1,G2) -> Gt that maps any two group elements from G1 and G2 respectively to an element in the third group Gt. All groups have the same order, q, the number of elements in the group. The accumulator scheme implemented uses Type-3 pairings such that G1 != G2 and there are no efficiently computable homomorphisms between G1 and G2. An introduction to pairings can be found here.
NOTE: This scheme must use a specific pairing friendly elliptic curve. Believe it will be using BLS-381. But should confirm. For implementations to be interoperable they must use the same curve (or possibly support multiple, but then would have to identify the curve in this data somewhere. Feels like unnecessary complexity)
Formally define a type-3 bilinear curve setup? Should this go in the appendix?
A Private Credential Definition with revocation enabled has the following format. In this, the
details of the p_key
element are hidden, as they are the same as was covered
above.
{
"p_key": {
"p": "123...782",
"q": "234...456"
},
"r_key": {
"x": "332...566",
"sk": "992...237"
}
}
r_key
is an object defining the private key for the CKS revocation scheme.x
is a Big (128-bit?) integer selected at random from the the group of integers defined by the order of the bilinear groupsq
sk
is a Big (128-bit?) integer selected at random from the the group of integers defined by the order of the bilinear groupsq
x
and sk
are used as part of the revocation public key generation as defined below.
A Credential Definition with revocation enabled has the following format (from this
example Credential Definition on the
Sovrin MainNet). In this, the details of the primary
element are hidden, as
they are the same as was covered above.
{
"issuerId": "did:indy:sovrin:F72i3Y3Q4i466efjYJYCHM",
"schemaId": "did:indy:sovrin:F72i3Y3Q4i466efjYJYCHM/anoncreds/v0/SCHEMA/state_license/4.2.0",
"type": "CL",
"tag": "latest",
"value": {
"primary": {...},
"revocation": {
"g": "1 154...813 1 11C...D0D 2 095..8A8",
"g_dash": "1 1F0...000",
"h": "1 131...8A8",
"h0": "1 1AF...8A8",
"h1": "1 242...8A8",
"h2": "1 072...8A8",
"h_cap": "1 196...000",
"htilde": "1 1D5...8A8",
"pk": "1 0E7...8A8",
"u": "1 18E...000",
"y": "1 068...000"
}
}
}
All attributes in the revocation
item represent elliptic curve points that are members of either G1 or G2. Group elements of G1 are represented using 3 64 digit hex integers, wheras G2 elements are represented using 6 64 digit hex integers. The revocation
attributes define a CKS public key that can be used to authenticate updates from the issuer to the accumulator.
In the following, only the revocation
item is described, as the rest of items (primary
, ref
, etc.) are described in the previous section of this document.
revocation
is the data used for managing the revocation status of credentials issued using this Credential Definition.g
is a generator for the elliptic curve group G1g_dash
is a generator for the elliptic curve group G2h
is a random elliptic curve element selected from G1h0
is a random elliptic curve element selected from G1h1
is a random elliptic curve element selected from G1h2
is a random elliptic curve element selected from G1h_cap
is a random elliptic curve element selected from G2htilde
is a random elliptic curve element selected from G1pk
is the public key in G1 for the issuer respective to this accumulator. (g^sk)u
is a random elliptic curve element selected from G2y
is the an elliptic curve element in G1 calculated as h_cap^x, where x is selected at random by the issuer from the set Z_q.
§ Publishing the Credential Definition on a Verifiable Data Registry
Once constructed, the Credential Definition is published by the Issuer to a Verifiable Data Registry using the issuers preferred AnonCreds Objects.
For example, see this Credential Definition that is published in the Sovrin MainNet instance of Hyperledger Indy. Note that the contents of the Credential Definition that have are published to the Hyperledger Indy ledger, do not exactly match the Credential Definition data model. The specific AnonCreds Objects can describe how to resolve the contents stored on the ledger into the Credential Definition data model.
§ Issuer Create and Publish Revocation Registry Objects
Once the issuer has created a Credential Definition with revocation enabled, the issuer must also create and publish a Revocation Registry Definition and create and publish the first Revocation Status List for the registry.
In this section, we’ll cover the create and publish steps for each of the Revocation Registry Definition and Revocation Status List objects. The creation and publishing of the Revocation Registry Definition includes creating and publishing the TAILS_FILE for the Revocation Registry.
§ Creating the Revocation Registry Object
A secure process must be run to create the revocation registry object, taking the following input parameters.
revocDefType
: the type of revocation registry being created. This is alwaysCL_ACCUM
credDefId
: the ID of the Credential Definition to which the Revocation Registry is to be associatedtag
: an arbitrary string defined by the [ref: issuer], enabling an [ref: issuer] to create multiple Revocation Registry Definitions for the same Credential Definition.maxCredNum
: The capacity of the Revocation Registry, a count of the number of credentials that can be issued using the Revocation Registry.tailsLocation
: A URL indicating where the TAILS_FILE for the Revocation Registry will be available to all holders of credential issued using this revocation registry.
Three outputs are generated from the process to generate the Revocation Registry: the Revocation Registry object itself, the TAILS_FILE content, and the Private Revocation Registry object.
§ Revocation Registry Definition Object Generation
The Revocation Registry Definition object has the following data model. This example is from this transaction on the Sovrin MainNet and instance of Hyperledger Indy.
{
"issuerId": "did:web:example.org",
"revocDefType": "CL_ACCUM",
"credDefId": "Gs6cQcvrtWoZKsbBhD3dQJ:3:CL:140384:mctc",
"tag": "MyCustomCredentialDefinition",
"value": {
"publicKeys": {
"accumKey": {
"z": "1 0BB...386"
}
},
"maxCredNum": 666,
"tailsLocation": "https://my.revocations.tails/tailsfile.txt",
"tailsHash": "91zvq2cFmBZmHCcLqFyzv7bfehHH5rMhdAG5wTjqy2PE"
}
}
The items within the data model are as follows:
Update this to be the inputs for generating a Revocation Registry vs. the already published object
issuerId
- the Issuer Identifier of the revocation registry. MUST adhere to Issuer Identifiers rules and MUST be the sameissuerId
as the Credential Definition on which the Revocation Registry is based.revocDefType
- the type of revocation registry (This is currently alwaysCL_ACCUM
)credDefId
- The id of the Credential Definition on which the Revocation Registry is based.tag
- an arbitrary string defined by the [ref: issuer], enabling an [ref: issuer] to create multiple Revocation Registry Definitions for the same Credential Definition.value
- The value of the revocation registry definitionpublicKeys
- Public keys data for signing the accumulator; the public key of a private/public key pairaccumKey
- Accumulator key for signing the accumulatorz
- a public key used to sign the accumulator (described further below)
maxCredNum
- The maximum amount of Credentials that can be revoked in the Revocation Registry before a new one needs to be startedtailsLocation
- The URL pointing to the related tails filetailsHash
- The hash of the tails file TAILS_FILE (see also: next section) resulting from hashing the tails file version prepended to the tails file as SHA256 and then encoded to base58.
As noted, most of the items come directly from the input parameters provided by
the issuer. The z
Revocation Registry accumulator public key is
generated using (TODO: fill in details) algorithm. The use of the accumulator
public key is discussed in the Credential Issuance section, when the publication
of revocations is described. The calculation of the tailsHash is described in
the next section on TAILS_FILE
generation.
The identifier for the Revocation Registry is dependent on where the Revocation Registry is published and the AnonCreds method used.
§ Tails File and Tails File Generation
The second of the outcomes from creating of a Revocation Registry is a TAILS_FILE. The contents of a TAILS_FILE is an array of calculated
points on curve G2
, one for each credential in the registry. Thus, if the Revocation Registry has a capacity (maxCredNum
) of 1000, the TAILS_FILE holds
an array of 1000 G2
curve points. Each credential issued using the Revocation Registry is
given its own index (1 to the capacity of the Revocation Registry) into the array,
the index of the point for that credential. The contents of the TAILS_FILE is needed by the holder to produce
(if possible) a “proof of non-revocation” to show their issued credential has
not been revoked.
The process of generating the points that populate the TAILS_FILE are tail[index] = g_dash * (gamma ** index)
Detailed process for tails file generation:
- Create and open the tails file.
- To generate a tail point for an attribute located at a specific index, follow the steps.
- Convert index into an array of bytes(
u8
) using little endian ordering. - Create an element belonging to the finite field group from the
u8
array. - Calculate
pow
by doing modular exponentiation of revocation private key(gamma
) with the finite field element previously calculated. - Multiply
pow
byg_dash
, which is the generator of elliptic curve groupG2
, and this should be the required point on the curve. - Convert this tail point to an array of bytes(
u8
), and put them into the file as a slice buffer. - Repeat for all the attributes from index to , by calculating . Note that Instead of inserting in the sequence, insert the value (the first value in the sequence) in its place, and then continue with and on to . is not used by holders generating the Non-Revocation Proof and a dummy value is inserted in its place.
- Close the file buffer.
Relevant links: Anoncreds-rs repository, Anoncreds-CLSignatures repository
The process for hashing the TAILS_FILE is as follows:
- Append the tails file version and all the bytes of
G2
curve points one by one into a hasher. - Compute the hash digest using
SHA256
hashing algorithm.
The SHA256 hash of the array of points is returned to be inserted into the tailsHash
item of the Revocation Registry object (as described in the previous
section). Typically, the array is streamed into a
file (hence, the term “Tails File”) and published to a URL indicated by
the tailsLocation
input parameter provided by the issuer.
The format of a TAILS_FILE is as follows:
- First two bytes are version number(currently
0u8 2u8
) - A list of the points, one per credential in the Revocation Registry. Each point is a collection of three integers implemented as points in 3 dimensions as per
ECP2
. Each point is 3x4 = 12 bytes long.
Thus the total size of a Tails File is 2+ 12*Size of the Revocation Registry
+6 (the L+1 entry).
While not required, the Hyperledger Indy community has created a component, the “Indy Tails
Server,” which is basically a web
server for tails files. Holders get the tailsLocation
during the
issuance process, download the TAILS_FILE (ideally) once and cache it
for use when generating proofs of non-revocation when creating a presentation
that uses its revocable verifiable credential. How the TAILS_FILE is
used is covered elsewhere in this specification:
- in the section about the issuer publishing credential revocation state updates, and
- in the section about holders creating a proof of non-revocation.
§ Revocation Registry Definition Object Generation
In addition to generating the Revocation Registry object, a Private Revocation Registry object is generated and securely stored by the issuer. The data model and definition of the items in the Private Revocation Registry is as follows:
To Do: Fill in the details about the Revocation Registry Definition
§ Publishing the Revocation Registry Object
Once constructed, the Revocation Registry is published by the issuer in a
Verifiable Data Registry using the issuer’s AnonCreds Objects. For example, see this
Revocation Registry that is published
on the Sovrin MainNet instance of Hyperledger Indy. The binary TAILS_FILE associated with the Revocation Registry can be downloaded from the
tailsLocation
in the Revocation Registry object.
§ Creating the Initial Revocation Status List Object
Published Revocation Status List objects contain the state of the Revocation Registry at a given point in time such that holders can generate a proof of non-revocation (or not) about their specific credential and verifiers can verify that proof. An initial Revocation Status List is generated and published immediately on creation of the Revocation Registry so that it can be used immediately by holders. Over time, additional Revocation Status List objects are generated and published as the revocation status of one or more credentials within the Revocation Registry change.
A secure process must be run to create the initial Revocation Status List object, taking the following input parameters.
revRegId
: the ID of the Revocation Registry for which the initial Revocation Status List is to be generated.- The process uses this identifier to find the associated Private Revocation Registry to access the information within that object.
revocationList
- A bit array of lengthmaxCredNum
that indicates whether a credential is initially revoked or not. The value of1
indicates the credential is initially revoked, the value of0
indicates the credential is initially unrevoked.
The process collects from the identified Private Revocation Registry information to calculate the cryptographic accumulator value for the initial Revocation Status List, including:
revocDefType
: the type of revocation registry. This is currently alwaysCL_ACCUM
maxCredNum
: The capacity of the Revocation Registry, a count of the number of credentials that can be issued using the Revocation Registry.tailsArray
: The contents of the TAILS_FILE, the array of primes, one for each credential to be issued from the Revocation Registry.privateKey
: The accumulator private key for the Revocation Registry.
With the collected information, the initial cryptographic accumulator for the Revocation Registry can be created. The format of the identifier for the Revocation Status List is dependent on the AnonCreds Objects Method used by the issuer.
In simple terms, the cryptographic accumulator at any given point in time is the (modulo) product of the primes for each non-revoked credential in the Revocation Registry.
If all of the credentials are initially revoked (revocationList
only contains 1
values), the accumulator value is 0
.
The accumulator is calculated using the following steps:
To Do: Adding the algorithm for calculating the accumulator
THe following is an example of an initial, published Revocation Status List object:
{
"revRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960",
"revocationList": [0, 1, 1, 0],
"currentAccumulator": "21 124C594B6B20E41B681E92B2C43FD165EA9E68BC3C9D63A82C8893124983CAE94 21 124C5341937827427B0A3A32113BD5E64FB7AB39BD3E5ABDD7970874501CA4897 6 5438CB6F442E2F807812FD9DC0C39AFF4A86B1E6766DBB5359E86A4D70401B0F 4 39D1CA5C4716FFC4FE0853C4FF7F081DFD8DF8D2C2CA79705211680AC77BF3A1 6 70504A5493F89C97C225B68310811A41AD9CD889301F238E93C95AD085E84191 4 39582252194D756D5D86D0EED02BF1B95CE12AED2FA5CD3C53260747D891993C",
"timestamp": 1669640864487
}
The items in the data model are:
revRegDefId
: the identifier of the associated Revocation Registry Definition. The format of the identifier is dependent on the AnonCreds Objects Method used by the issuer.revocationList
: Bit array defining the status of the credential in the [ref: Revocation Registry]. A value of1
means the credential is revoked, a value of0
means the credential is not revoked.currentAccumulator
: the calculated cryptographic accumulator reflecting the initial state of the Revocation Registrytimestamp
: the timestamp at which the accumulator value is valid
§ Publishing the Initial Initial Revocation Status List Object
Once constructed, the initial Revocation Status List is published by the issuer in a Verifiable Data Registry using their selected AnonCreds Objects Method.
It is not required for the Verifiable Data Registry to store the revocation list as defined in this model. For example, the Indy ledger uses deltas (Revocation Registry Entries) to store the change in revoked/un-revoked indices instead of storing the entire revocation list. It is also possible to compress the revocationList
entry using e.g. GZIP to reduce the size on the ledger.
§ Holder Create and Store Link Secret
To prepare to use AnonCreds credentials, the Holder must create a link secret, a unique identifier that allows credentials issued to a Holder to be bound to that Holder and presented without revealing a unique identifier, thus avoiding correlation of credentials by Verifiers. The link_secret is kept private by the Holder. The link secret is used during the credential issuance process to bind the credential to the holder and in the generation of a presentation. For the latter, it allows the holder to create a zero knowledge proof that they were issued the credential by demonstrating knowledge of the value of the link_secret without sharing it. The details of how the link_secret is used to do this is provided in the issuance, presentation generation and verification sections of this specification.
The link secret is a sufficiently random unique identifier. For
example, in the Hyperledger Indy implementation, the link secret is
produced by a call to the Rust
uuid Crate’s new_v4()
method to
achieve sufficient randomness.
Once generated, the link_secret is stored locally by the Holder for use in subsequent issuance and presentation interactions. If lost, the Holder will not be able to generate a proof that the credential was issued to them. The holder generates only a single link_secret, using it for all credentials the holder is issued. This allows for verifiers to verify that all of the credentials used in generating a presentation with attributes from multiple credentials were all issued to the same Holder without requiring the Holder to disclose the unique identifier (link_secret) that binds these credentials together.
There is nothing to stop a Holder from generating multiple link_secrets and contributing them to different credential issuance processes. However, doing so prevents the Holder from producing a presentation combining credentials issued to distinct link_secrets that can be proven to have been issued to the same entity. It is up to the Verifier to require and enforce the binding between multiple credentials used in a presentation.
§ AnonCreds Issuance Data Flow
The issuance of an anonymous credential requires several steps and involves the roles issuer, holder as well as the Verifiable Data Registry (see diagram below).
Data Registry participant I as Issuer participant H as Holder I ->> I: Create Credential Offer I ->> H: Send Credential Offer H ->> H: Verify Credential Offer opt H ->> L: Request Schema L ->> H: Return Schema end H ->> L: Request Credential Definition L ->> H: Return Credential Definition H ->> H: Create Credential Request H ->> I: Send Credential Request I ->> I: Verify Credential Request I ->> I: Issue Credential I ->> H: Send Credential H ->> H: Verify and Store Credential rect rgb(191, 223, 255) Note left of H: 💡The "Verifier" and "Schema Publisher" roles are
omitted in this diagram, since they do not participate
in the credential issuance data flow. end
The issuer prepares a Credential Offer for the holder (step 1). A Credential Offer includes a commitment about the credential (referencing a Public Credential Definition) the issuer is intending to issue to the holder. The issuer sends the Credential Offer to the holder (step 2), who evaluates the offer (step 3) and fetches data about the offer (the Public Credential Definition) from the Verifiable Data Registry (steps 4-7).
Using the data from the Credential Offer and the Public Credential Definition retrieved from the Verifiable Data Registry, the holder prepares a Credential Request (step 8), a formal request to the issuer to issue a credential based on the given Public Credential Definition to the holder. The Credential Request includes a cryptographic commitment to the holder's link secret. The holder sends the Credential Request to the issuer (step 9).
The issuer verifies and decides whether to accept the Credential Request (step 10) and if so, prepares the credential (step 11). The issuer sends the credential to the holder (step 12), who verifies the credential and (usually) securely stores it (step 13).
Details about each step in the issuance process are covered in the following sections.
§ Credential Offer
The AnonCreds issuance process begins with the issuer constructing and sending a Credential Offer to the potential holder. The Credential Offer contains the following JSON elements:
{
"schema_id": string,
"cred_def_id": string,
"nonce": string,
"key_correctness_proof" : <key_correctness_proof>
}
schema_id
: The ID of the Schema on which the Public Credential Definition for the offered Credential is based.cred_def_id
: The ID of the Public Credential Definition on which the Credential to be issued will be based.nonce
: A random number generated for one time use by the issuer for preventing replay attacks and authentication between protocol steps. Thenonce
must be present in the subsequent Credential Request from the holder.key_correctness_proof
: The Fiat-Shamir transformation challenge value in the non-interactive mode of Schnorr Protocol. It is calculated by the issuer as the proof of knowledge of the private key used to create the Credential Definition. This is verified by the holder during the creation of Credential Request.
The JSON content of the key_correctness_proof
is:
"key_correctness_proof": {
"c": "103...961",
"xz_cap": "563...205",
"xr_cap": [
[
"<attribute 1>",
"821...452"
],
[
"master_secret",
"156...104"
],
[
"<attribute 1>",
"196...694"
]
]
}
The values in the proof are generated as follows:
c
: (a BigNumber) can be viewed as the committed value derived from the hash of the concatenated byte values in the process of creating the Credential Definition.
where
-
where , and are values in the Public Credential Definition
-
are the values in the map in Public Credential Definition, individual attribute public keys
-
is similar to which equals to , where is a randomly selected integer between and
-
is similar to , which equal to , where are randomly selected integers between and
-
xz_cap
: -
xr_cap
: for attributes
Both xz_cap
and the second element in the tuple of the xr_cap
vector
are BigNumbers.
The issuer sends the Credential Offer to the holder.
§ Credential Request
A Credential Request is a formal request from a holder to an issuer to get a credential based on the Credential (and the referenced Public Credential Definition) sent by the issuer to the holder.
On receipt of the Credential Offer, the holder retrieves the referenced Public Credential Definition from a Verifiable Data. The holder MAY want to retrieve the Schema referenced in the Credential Offer and verify the consistency between the list of attributes in the Schema and in the Public Credential.
The nonce of the Credential Offer is used to generate the proof of correctness for blinded credential secrets, where it is hashed with the blinded secrets to create the proof which is sent to the issuer.
In addition, the holder also requires access to their link.
§ Verifying the Key Correctness Proof
The holder must first verify the key_correctness_proof
in the Credential Offer using data from the referenced Public Credential Definition. The
key_correctness_proof
data is described in the previous
section about the Credential Offer.
The key_correctness_proof
verification is as follows:
- Check that all attributes in Public Credential Definition and
master_secret
(an attribute that will be related to the link_secret) are included inxr_cap
. - Compute , where .
- If and , then . The proof is accepted.
For , we first find the multiplicative inverse of
Then
The same can be derived for all by finding the multiplicative inverse of , where {1 < i < L} for attributes.
§ Constructing the Credential Request
The holder constructs the following Credential Request JSON structure:
{
"prover_did": "BZpdQDGp2ifid3u3Up17MG",
"cred_def_id": "GvLGiRogTJubmj5B36qhYz:3:CL:8:faber.agent.degree_schema",
"blinded_ms": {
# Structure detailed below
},
"blinded_ms_correctness_proof": {
# Structure detailed below
},
"nonce": "604812518357657692681285"
}
entropy
: a required string.- Called
prover_did
in earlier AnonCreds implementations, and calledprover_id
in Ursa,entropy
is a random alphanumeric string generated by the holder and used by the issuer to add entropy in generating the credential signature. The value is combined by the issuer with the credential revocation index (cred_idx
) if the credential is revocable, and the resulting string is hashed to create thecredential_context
, an input to the credential signing process. Thecredential_context
is them2
item in the issued verifiable credential signature. - Historically in Aries agent implementations, the
prover_did
was populated by the holder with a DID they hold, usually the DIDComm peer-to-peer DID shared by the the holder to the issuer. However, the item is not verified by the issuer as a DID nor as an identifier for the holder, and as such an random string is sufficient. - The holder can verify the provide
entropy
value was used by the [[ref: issuer] in generating the signature by combiningentropy
with thecred_idx
value from the issuer (if the credential is revocable), hashing the resulting string and checking that the hash matchesm2
in the credential signature.
- Called
cred_def_id
: The ID of the Public Credential Definition on which the Credential to be issued will be based.blinded_ms
: The link secret in its blinded form. Described in detail in the section Blinding the Link Secret (below).blinded_ms_correctness_proof
: The Blinded Secrets Correctness Proof of the blinded link secret. Described in detail in the section The Blinded Link Secret Correctness Proof (below).nonce
: Used for preventing replay attacks and authentication between protocol steps. The holder creates an 80 bit nonce in the request which is a randomly generated number.
Once constructed, the holder sends the Credential Request to the issuer, who then can reply to the holder by sending an issued credential.
§ Blinding the Link Secret
The blinded_ms
(blinded link secret) in the Credential Request
is a
cryptographic commitment by the holder to the link secret. The
blinded_ms
will be signed by the issuer, placed in the credential, and
during presentations, is proven by the holder to be associated with the
link_secret using a proof of knowledge, without revealing the link_secret itself. This is the capability that enables the binding of the
credential to the holder without revealing a correlatable identifier.
The blinding factor is a secret held by the holder for blinding the link secret before sending it to the issuer, and used later when generating the proof of knowledge that the link secret was used in the signature received from the issuer. The blinding factor, is created by the holder generating a 3152-bit random number.
The process of blinding the link secret uses the issuer's
CredentialPrimaryPublicKey
, , which is included in the Public Credential Definition,
and contains z
, r
, s
and n
(described
here). While r
contains
the public keys for all of the attributes to be signed, the only one of interest
in this process is
The link secret, is blinded by
is multiplied by the blinding factor, ,
The resulting blinded link secret data structure inserted into the Credential Offer is defined as follows:
"blinded_ms": {
"u": "331...544",
"ur": null, # Populated when the credential definition supports revoation
"hidden_attributes": [
"master_secret"
],
"committed_attributes": {}
}
-
u
: is the blinded link secret which is . -
ur
: isnull
if revocation is not active for the [[ref: Public Credential Definition], and if revocation is active where is randomly selected quadratic residue of order of the bilinear groupsq
and is part of the revocation public key. -
hidden_attributes
: is an array of hidden attributes from the list of Public Credential Definition. For AnonCreds v1.0, it is always a single entry ofmaster_secret
.- The holder's blinded link secret is a default hidden attribute in AnonCreds, meaning it is not explicitly defined in the Schema list of attributes but is included in both the Public Credential Definition and all issued credentials. Whilst it is cryptographically possible to have multiple hidden attributes, in this version of AnonCreds, only link secret is used.
-
committed_attributes
: An empty list of attributes in this version of AnonCreds.
§ The Blinded Link Secret Correctness Proof
In addition to creating the blinded link secret, the holder also creates a blinded link secret correctness proof and inserts it into the Credential Request. The data structure for the blinded link secret correctness proof is as follows:
"blinded_ms_correctness_proof": {
"c": "702...737",
"v_dash_cap": "202...924",
"m_caps": {
"master_secret": "907...913"
},
"r_caps": {}
}
The values in the proof are generated as follows:
c
: (a BigNumber) can be viewed as the committed value derived from the hash of the concatenated byte values in the process of creating the Credential Definition and thenonce
value .
where
-
is described above.
-
where is randomly selected 3488-bit value and is 593-bit value by reference Anonymous credentials with type-3 revocation by Dmitry Khovratovisch, Michael Lodder and Cam Parra
-
is the nonce value.
-
v_dash_cap
: , where is the blinding factor and is a 3488-bit random number. -
m_caps
: -
r_caps
: is an empty structure in this version of AnonCreds.
§ Issue Credential
After the issuer receives the Credential Request from the holder, the issuer processes the Credential Request and decides whether to issue the credential as requested in the Credential Request to the holder. In this section, we’ll cover issuing a credential that cannot be revoked, and then cover the additional steps/data elements in issuing a credential that can be revoked.
§ Verifying the Credential Request
Before deciding to issue the credential, the issuer must first verify the Credential Request from the holder by checking first the nonce, and then the blinded link secret correctness proof.
The blinded_ms_correctness_proof
is verified by issuer. The blinded_ms_correctness_proof
verification is as follows:
- Compute , where .
- If , then . The proof is accepted.
For , we first find the multiplicative inverse of
Then
Once the Credential Request is verified and if the issuer decides to proceed with issuing the credential, the credential creation process is performed.
§ Encoding Attribute Data
The Anoncreds signature is not applied on the data attributes themselves, but rather on 32-byte integers encoded from the data attribute values. In the current version of AnonCreds, the process of encoding the attributes (also known as canonicalization) is
a task performed by the issuer, who should do the encoding in a manner understood by all potential verifiers such that any verifier can confirm that the revealed raw
attributes in the presentation produce
the encoded value signed by the issuer. To enable the broadest possible interoperability, the Hyperledger Aries community formalized the following encoding rules for the raw
attribute values in an AnonCreds credential, and those rules are adopted into this specification, as follows:
- keep any integer as is
- convert any string integer (e.g. “1234”) to be an integer (e.g. 1234)
- for data of any other type:
- convert to string (use string “None” for null)
- encode via utf-8 to bytes
- apply SHA-256 to digest the bytes
- convert the resulting digest bytes, big-endian, to integer
- stringify the integer as a decimal.
An example implementation in Python of these rules can be found here.
A gist of test value pairs can be found here.
To enable broad interoperability, and to improve the security of AnonCreds by
eliminating the risk of malicious holders altering the raw
data
values in hopes that the verifier will not check the encoding as part
of the overall presentation verification, future versions of AnonCreds
credentials will not include issuer-created encoded values in the AnonCreds credentials, and will instead
require the encoding of the raw
data values on as needed basis.
Implementations of AnonCreds MAY
- Verify the encoded values provided by the issuer and reject the credential input if the encoding does not follow the encoding rules in this specification.
- Ignore the issuer-provided encoded values and calculate the encoded values before generating signatures based on the encoding rules above.
- Ignore the encoded values placed in credentials and/or presentations and generate the encoded values “on-the-fly” based on the encoding rules above.
§ Constructing a Credential
To construct a non-revocable credential, the issuer must have available:
- The identifiers for the schema and Public Credential Definition.
- The Private Credential Definition data to be used in signing the credential.
- The
raw
value for each attribute to be included in the credential. - The
encoded
value derived from eachraw
value using the encoding attribute data rules (above). - The blinded link secret from the holder's Credential Request.
Additional data is needed for issuing a revocable credential, as described in the section Supporting Revocation in a Credential.
The JSON of a generated AnonCreds credential is as follows:
{
"schema_id": string,
"cred_def_id": string,
"rev_reg_id": null,
"values": {
"first_name": {
"raw": "Alice",
"encoded": "113...335"
},
"last_name": {
"raw": "Garcia",
"encoded": "532...452"
},
"birthdate_dateint": {
"raw": "19981119",
"encoded": "19981119"
}
},
"signature": {
"p_credential": {
"m_2": "992...312",
"a": "548...252",
"e": "259...199",
"v": "977...597"
},
"r_credential": null
},
"signature_correctness_proof": {
"se": "898...935",
"c": "935...598"
},
"rev_reg": null,
"witness": null
}
schema_id
: is the ID of the Schema upon which the Public Credential Definition was generated.cred_def_id
: is the ID for the Public Credential Definition on which the Credential issued is based.rev_reg_id
isnull
if the credential is not revocable. A description of the element when the credential is revocable is in the section Supporting Revocation in a Credential.values
is the list of attributes in the credential, including for each:- the name of the attribute (in this case
first_name
,last_name
, andbirth_dateint
), - the
raw
data for the attribute, and - the
encoded
data for the attribute, derived from theraw
value has defined in the encoding attribute data rules.
- the name of the attribute (in this case
signature
is the cryptographic signature generated for the credential.- A description of the
p_signature
elements and generation process are in the section The Credential Signature. r_credential
isnull
if the credential is not revocable. A description of ther_signature
elements and generation process when the credential is revocable are in the section Supporting Revocation in a Credential.
- A description of the
signature_correctness_proof
is the Signature Correctness Proof generated for the credential. A description of the elements and generation process are in the section The Credential Signature Correctness Proof.rev_reg
isnull
if the credential is not revocable. A description of the element and generation process when the credential is revocable are in the section Supporting Revocation in a Credential.witness
isnull
if the credential is not revocable. A description of the element and generation process when the credential is revocable are in the section Supporting Revocation in a Credential.
Once constructed, the issuer sends the credential to the holder for verification and storage.
Please note the data attribute “birth_dateint” in the example above. The convention of
putting a _dateint
suffix on a credential attribute name is used to indicate
that the field contains a date in the form of an integer, such as “2022.11.21”
as the integer “20221121” (the number 20,221,121). By putting the date in that
form, AnonCreds predicates can be applied to the data, such as proving “older
than 21” based on date of birth without sharing the date of birth. This
convention was initially defined
here
by the Hyperledger Aries
community.
§ The Credential Signature
The credential signature elements are constructed as follows:
- Compute where is a random 2724-bit number with most significant bit as and is a random prime such that
- Compute where are primes generated during issuer setup, and is the multiplicative inverse of .
Add the details about the credential signature data elements
m_2
is the TO BE ADDED. It is constructed as follows:- TO BE ADDED
a
is the TO BE ADDED. It is constructed as follows:- TO BE ADDED
e
is the TO BE ADDED. It is constructed as follows:- TO BE ADDED
v
is the TO BE ADDED. It is constructed as follows:- TO BE ADDED
§ The Credential Signature Correctness Proof
The credential signature correction proof elements are constructed as follows:
Using random , compute
where is the nonce
from credential request and is SHA-256 hashing algorithm.
Signature correctness proof .
se
is the credential signature correctness proof.c
is the witness for the credential signature correctness proof.
§ Supporting Revocation in a Credential
When a credential is revocable, in addition to the listed inputs needed for constructing a credential, the issuer also needs the ID and private Revocation Registry data. Using the inputs, the revocation-related fields in the credential JSON are populated. The following describes the elements and how they are produced.
rev_reg_id
is the ID of the Revocation Registry Definition published on a Verifiable Data Registry that is to be used by the holder when trying to generate a Non-Revocation Proof for this credential as part of an AnonCreds presentation.
r_credential
is the following JSON data structure:
"r_credential": {
"sigma": "1 14C...8A8",
"c": "12A...BB6",
"vr_prime_prime": "0F3...FC4",
"witness_signature": {
"sigma_i": "1 1D72...000",
"u_i": "1 0B3...000",
"g_i": "1 10D...8A8"
},
"g_i": "1 10D7...8A8",
"i": 1,
"m2": "FDC...283"
}
The items in the data structure are:
c
: is a random number belonging in the group G2vr_prime_prime
: is also a random number belonging in the group G2sigma
: is calculated as
where , are from revocation public key, is from the blinded credential secrets, where is the issuer’s accumulator index, is from revocation public key, and is from the revocation private key.
witness_signature
:sigma_i
: is calculated asu_i
: isg_i
: is a point in curve G1 which calculated by
g_i
: is a point in curve G1 which calculated byi
: is the issuer’s accumulator indexm2
: is the credential context which acts as a linkable identifier to the holder.
rev_reg
is the following JSON data structure:
"rev_reg": {
"accum": "21 118...1FB"
}
The item in the data structure is:
accum
: is the accumulator value of the issuer which is updated with the new tails point as soon as new revocation credential is generated, and published to the public ledger.
witness
is the following JSON data structure:
"witness": {
"omega": "21 124...AC8"
}
The item in the data structure is:
omega
: is calculated by where is the current set of non revoked indices and is the number of indices contained in the accumulator.
§ Receiving a Credential
On receipt of a credential from an issuer, the holder must verify the credential and, if verified, will likely store the credential in a secure location.
To verify the signature_correctness_proof
, the holder does the following:
- Verify that is a prime and lies within it’s range.
- Compute
- Verify
- Compute
- Verify
The verifying and securely storing of the credential by the holder completes the AnonCreds issuance process.
An AnonCreds credential is expected to be retained by the holder that participated in the issuance process. The holder should not transfer the credential to others for their use, and should only use the credential to generate an AnonCreds verifiable presentation, as outlined in the AnonCreds Presentation section of this specification.
§ AnonCreds Presentation Data Flow
Data Registry participant SP as Schema Publisher participant I as Issuer participant H as Holder participant V as Verifier Note over L, V: AnonCreds Presentation Data Flow V->>V: Create presentation request V->>H: Send presentation request H->>H: Select credentials to satisfy the presentation request H->>L: If necessary: Request revocation entries L->>H: Return revocation entries H->>H: Generate presentation H->>V: Send presentation V->>L: Request credential definitions, revocation entries L->>V: Return credential definitions, revocation entries V->>V: Verify presentation
The flow of operations to request, create, and verify a verifiable presentation is illustrated in the AnonCreds Presentation Data Flow sequence diagram.
The Verifier starts the process in step 1 by creating and sending a presentation request to the Holder.
In step 2, the Verifier sends the presentation request to the Holder.
In steps 3-6, the Holder collects the required information and creates the verifiable presentation to satisfy the presentation request received from the Verifier. If the Holder does not have the necessary credentials to satisfy the request, the Holder may ignore the presentation.
In step 7, the Holder sends the verifiable presentation according to the presentation request to the Verifier.
In step 8-10, the Verifier collects the required information and verifies the verifiable presentation and accepts it if the signature is valid, otherwise rejects the verifiable presentation.
Question: VDR access for schema, revocation etc. retrieval mandatory?
§ Create Presentation Request
The verifier starts the presentation process in step 1 of the AnonCreds Presentation Data Flow by creating and sending a presentation to the holder.
The presentation request provides information about the attributes and predicates the verifier is asking the the holder to reveal, restrictions on what verifiable credentials can be the sources for the attributes and predicates, and limitations on the freshness of the credential revocation status. Presentation requests are defined at the “business logic” layer, with any cryptographic processing applied. The verification process includes verifications that the presentation satisfies the request. The verifier SHOULD validate that the presentation satisfies the business requirements for which the presentation was provided.
In reading this section, the term attribute
is used in two ways, and readers
should be aware of the context of each use. A presentation request has **requested
attributes that are to be included in the presentation provided from the holder. Those requested attributes in turn reference attribute names and
values from source verifiable credentials held by the holder.
The presentation request is created by the verifier in JSON format, as follows:
{
"name": string,
"version": string,
"nonce": string,
"requested_attributes": {
"<attr_referent>": <attr_info>,
...,
},
"requested_predicates": {
"<predicate_referent>": <predicate_info>,
...,
},
"non_revoked": Optional<non_revoc_interval>,
"ver": Optional<str>
}
name
is a string set by the verifier, a name for the presentation request.version
is a string set by the verifier, the version of the presentation requestnonce
is a string, a decimal, 80-bit number generated by the verifier that SHOULD be unique per presentation request. The nonce is included in the request to prevent replay attacks through its use in creating and verifying the presentation.requested_attributes
specify the set of requested attributesattr_referent
is a verifier-defined identifier for the requested attribute(s) to be revealed.attr_info
describes a requested attribute. See attr_info
requested_predicates
specify the set of requested predicatespredicate_referent
is a verifier-defined identifier for the requested predicate.predicate_info
describes a requested predicate. See predicate_info
non_revoked
specifies an optional non-revocation intervalnon_revoc_interval
. See the Request Non-Revocation Proofs section.ver
is an optional string, specifying the presentation request version.- If omitted, “1.0” is used by default.
- “1.0” to use unqualified identifiers for restrictions
- “2.0” to use fully qualified identifiers for restrictions
attr_info
has the following format:
{
"name": <string>,
"names": <[string, string]>,
"restrictions": <restrictions>,
"non_revoked": <non_revoc_interval>,
}
All of the items are optional, but one of name
or names
MUST be included, and not both.
name
is a string, the name of an attribute from a source credential.- The name is case insensitive with spaces ignored.
names
is a array of strings, the names of attributes from a source credential- The names are case insensitive with spaces ignored.
- The attribute names MUST be sourced from a single credential.
restrictions
is a condition on the source credential that can be used to satisfy this attribute request.- See restrictions for details about supported restrictions.
- Omitting
restrictions
implies that:- The holder MAY provide self-attested attributes for the request in the presentation, or
- that the name(s) of the requested attributes match the name(s) of the claim(s) in the source verifiable credential.
non_revoked
specifies a non-revocation intervalnon_revoc_interval
for this requested attribute.- See Request Non-Revocation Proofs section.
- If
non_revoked
is defined at the outer level of the JSON and is not defined at theattr_info
level, the out level data applies to the attribute. - If
non_revoked
is defined at the outer level of the JSON AND at theattr_info
layer, theattr_info
data applies to the attribute.
predicate_info
has the following format:
{
"name": string,
"p_type": string,
"p_value": int,
"restrictions": <restrictions>,
"non_revoked": <non_revoc_interval>,
}
name
(required) is a string, the name of an attribute from a source credential to use in the predicate expression.- The name is case insensitive and spaces are ignored.
- To be useful, the attribute in the source credential MUST be an integer, but that requirement cannot be enforced. The verifier MUST understand how the attribute value is set by the issuer(s) in the expected source credentials.
p_type
is a string, the type of the predicate. Possible type values are [“>=”, “>”, “<=”, “<”].p_value
is an integer value.- The boolean expression that is to proven in zero knowledge is evaluated as:
“
<name> <p_type> <p_value>
.” For example, to check an “older than” based on date of birth, the expression might be “birth_dateint <= 20020116
”
- The boolean expression that is to proven in zero knowledge is evaluated as:
“
restrictions
is a condition on the source credential that can be used to satisfy this predicate request.- See restrictions for details about supported restrictions.
- If omitted, the only restriction on the requested predicate is that the
name
matches the attribute name in the source credential used to satisfy the predicate.
non_revoked
specifies a non-revocation intervalnon_revoc_interval
for this predicate attribute.- See Request Non-Revocation Proofs section.
§ Restrictions
The restrictions
item on attributes (optional) and predicates (required) is a
JSON structure that forms a logical expression involving properties of the
source verifiable credential. The holder must use source verifiable
credentials that satisfy the restrictions
expression for each
attribute/predicate entry. Each element of the logic expression is a property of
source credentials and a value to be matched for that property. The following
properties can be specified in the JSON. All except the marker
property is
specified with a value that must match the property. For the marker
property,
the value is always 1
.
schema_id
- the identifier of the schema upon which the source credential is based.schema_issuer_did
- the identifier, usually a DID, of the publisher of the schema upon which the source credential is based.schema_name
- thename
property of the schema upon which the source credential is based.schema_version
- theversion
property of the schema upon which the source credential is based.issuer_did
- the identifier, usually a DID, of the [[re: issuer]] of the source credential.cred_def_id
- the identifier of the Credential Definition of the source credential.attr::<attribute-name>::marker
- an attribute<attribute-name>
must exist in the source credential.- When used, the value of the JSON item must be “1”.
attr::<attribute-name>::<attribute-value>
- the attribute<attribute-name>
must be found in the source credential with a value of<attribute-value>
.- When this property is used, the verifer MUST request that the
<attribute-name>
be revealed as otherwise there is no way to be sure the restriction has been satisfied.
- When this property is used, the verifer MUST request that the
A boolean expression is formed by ORing and ANDing the source credential properties. The following JSON is an example. Any of the source credential properties listed above can be used in the expression components:
"restrictions": [
{
"issuer_did": "<did>",
"schema_id": "id"
},
{
"cred_def_id" : "<id>",
"attr::color::marker": "1",
"attr::color::value" : "red"
}
]
The properties in each list item are AND’d together, and the array elements are OR’d together. As such, the example above defines the logical expression:
The attributes must come from a source verifiable credential such that:
issuer_did = <did> AND
schema_id = <id>
OR
cred_def_id = <id> AND
the credential must contain an attribute name "color" AND
the credential must contain an attribute name "color" with the attribute value "red"
§ Request Non-Revocation Proofs
The presentation request JSON item non_revoked
allows the verifier to define an acceptable non-revocation interval for a requested
attribute(s) / predicate(s), as follows:
{
"from": Optional<int>,
"to": Optional<int>,
}
from
is an unsigned long long value, the Unix Time timestamp of the interval beginning.to
is an unsigned long long value, the Unix Time timestamp of the interval end.
As noted in the presentation request specification above, a non-revoked
item
be may at the outer level of the presentation request such that it applies to
all requested attributes and predicates, and/or at the attribute/predicate level, applying
only to specific requested attributes and/or predicates and overriding the outer layer item.
The non-revoked
items apply only to requested attributes/predicates in a presentation
that derive from revocable credentials. No proof of non-revocation is needed (or
possible) from credentials that cannot be revoked. Verifiers should be aware
that different issuers of the same credential type (same schemaId
) may or may
not use revocation for the credentials they issue.
The use of a “non-revoke interval” was designed to have the semantic meaning
that the verifier will accept a non-revocation Proof (NRP) from any
point in the from
to to
interval. The intention is that by being as flexible
as the business rules allow, the holder and/or verifier may
have cached VDR revocation data such that they don’t have to go to the
VDR to get additional RevRegEntry data. The verification of
the provided non-revocation interval in a presentation request is
limited. For additional details, see the
Verify Non-Revocation Proof section of this
specification.
In practice, the use of the interval is not well understood and tends to cause
confusion amongst those building presentation requests. The AnonCreds
community recommends using matching from
and to
values as outlined in the
Aries RFC 0441 Present Proof Best
Practices.
The verifier can then use business rules (outside of AnonCreds) to
decide if the revocation is sufficiently up to date.
While one might expect the to
value to always be the current time (“Prove the
credential is not revoked now”), its inclusion allows the verifier to
ask for a non-revocation proof sometime in the past. This addresses use cases
such as “Prove that your car insurance policy was not revoked on June 12, 2021
when the accident occurred.”
§ Presentation Request Example
The following is an example of a full presentation request for a presentation for a set of revealed attribute names from a single source credential, a self-attested attribute, and a predicate.
{
"nonce":"168240505120030101",
"name":"Proof of Education",
"version":"1.0",
"requested_attributes":{
"0_degree_uuid":{
"names":[
"name",
"date",
"degree"
],
"restrictions":[
{
"schema_name":"degree schema"
}
]
},
"0_self_attested_thing_uuid":{
"name":"self_attested_thing"
},
"non_revoked": {
"from": 1673885735,
"to": 1673885735,
}
},
"requested_predicates":{
"0_age_GE_uuid":{
"name":"birthdate_dateint",
"p_type":"<=",
"p_value":20030101,
"restrictions":[
{
"schema_name":"degree schema"
}
]
}
}
}
In step 2 of the AnonCreds Presentation Data Flow, the verifier sends the presentation request to the holder.
§ Generate Presentation
In step 3, 4, and 5 of the AnonCreds Presentation Data Flow, the holder collects the required information to create the verifiable presentation according to the presentation request received from the verifier.
Each attribute and predicate in the presentation request must be satisfied by a
source credential held by the holder that meets the associated
restrictions
item in the presentation request. The same source credential MAY
be used to satisfy multiple attributes and predicates. Each attribute in the
presentation request may specify (using the names
item) that multiple claims from the source credential must be shared. If there is no restrictions
item
in the presentation request, the holder MAY satisfy the presentation request
with self-attested attributes.
To prevent confusion, the term “attribute” in this section always refers to
the required_attributes
in a presentation request, and the term “claim” is
used for the data elements in a verifiable credential.
The verifier may specify in the presentation request that if some or all of the attributes/predicates are to be satisfied by revocable credentials, the holder must accompany the verifiable credential proofs with non-revocation proofs (NRPs) for the source credentials. The generation of NRPs is described in the generate non-revocation proofs section of the specification.
Often in discussions about verifiable presentations, the term “prover”
is used to indicate the participant generating the presentation. Throughout the
Hyperledger AnonCreds implementation the term prover
is used in the names of
methods performed by that participant. However, because in AnonCreds the holder and the prover are always the same entity, we’ll use holder to refer to the participant generating the requested presentation to
emphasize that the same entity is both issued credentials and generating
presentations from those credentials.
§ Collecting the Source Verifiable Credential Data
Before the holder can generate the presentation to satisfy a request, the source verifiable credentials that will be used in the presentation must be collected.
The source verifiable credentials found for use in generating a presentation must meet the following requirements:
- All of the source credentials MUST have been issued to the same link secret.
- The source credential for each presentation request attribute and predicate
must satisfy the attribute’s or predicate’s associated
restrictions
item, and must include claim names that match the attribute’sname
ornames
item, or claim name that match the requested predicate.
The mechanism to find the credentials in the holder’s wallet that satisfy a presentation request is outside the scope of this specification. As such, the remainder of this section covering how this process is done in Hyperledger Aries implementations is non-normative.
Aries implementations have historically used a mechanism called Wallet Query
Language (WQL) to find the source credentials in the holder agent’s
storage. Agents iterate through the presentation request attributes and
predicates, converting the restrictions
item from each into a corresponding
WQL query, and calling an Aries key management service, such as Aries Askar,
to return the credentials in the wallet that satisfy the query.
Completing the process results in a list of 0 or more source verifiable
credentials that satisfy each attribute and predicate. If there is not a source
verifiable credential for each, a business process must be invoked to decide if
or how to proceed. For example, if some of the attributes or predicates cannot
be satisfied with a credential already in the holder's storage, a
process to get the necessary additional verifiable credentials may be initiated.
If more than one verifiable credential satisfy any of the restrictions
items,
the holder software might select one to use by default, such as the
most recently issued, non-revoked of the credentials, and/or might invoke a user
interface to allow the entity that controls the holder software to
select from the set of possible credentials to use.
In order to proceed to the presentation generation step, there must be one credential selected for each attribute and predicate in the presentation request.
§ Prepare Inputs to Presentation Generator
The next step of the process to create a presentation is to prepare the inputs to a call to AnonCreds to generate the presentation. The following are the inputs to the generation process (implementation). The holder must prepare each of the inputs by getting data either from local storage or, in the case of public data, retrieving it from the appropriate verifiable data registry(ies). AnonCreds implementations may provide functions to help in preparing some of the data.
pres_req
– The presentation request from the verifier.credentials
– The list of credentials chosen by the holder for use in the presentation, including the request attributes and predicates to be populated from the each of the credentials. See note below.self_attested
- A Hash Map containing each attribute to be satisfied with a self-attested response. Each entry includes the name of a presentation request attribute, and the self-attested value for that attribute.link_secret
- The link secret for the credentials in the presentation.schemas_json
- A Hash Map containing theSchemaId
and completeSchema
for the schemas of the credentials in the presentation.credential_defs_json
- A Hash Map containing theCredentialDefinitionId
and the completeCredentialDefinition
for the credential definitions of the credentials in the presentation. Included in theCredentialDefintion
are the revocation related values of theCredentialDefinition
.
The credentials
data structure contains for each listed credential:
- The complete
credential
data structure, as received from the issuer. - A list of the presentation request attributes and predicates that will be
populated from the credential.
- For each of the source credential claim to be included in a request
attribute, an indicator if the credential is to be revealed or not
(
true
/false
) in the presentation.
- For each of the source credential claim to be included in a request
attribute, an indicator if the credential is to be revealed or not
(
- The
timestamp
for the selected RevRegEntry that will be used to produce the non-revocation proof, if required. - The
witness
for the credential based on the RevRegEntry being used to produce the non-revocation proof, if needed.
If the credential is not revocable, the latter two inputs are null
, and are
not used. See the later section on generating a presentation for a revocable
credential for details about populating
the timestamp
and witness
data elements.
The indicator of whether a claim is to be revealed or not in AnonCreds 1.0 must
be carefully understood by verifiers. While a verifer requests a set of claims
from the prover, the prover may choose to not reveal the raw
value of some of
those claims. If the prover does not reveal all of the requested claims,
AnonCreds treats the presentation as cryptographically verified. It is then
up to the verifier to decide, after cryptographic verification, if a
presentation with unrevealed values is acceptable for the business purpose of
the presentation.
§ Generate the Presentation
From the inputs, the presentation data is generated and put into the following data structure:
presentation_request
– The presentation request from the verifier.presentation
– The set of proofs generated to satisfy the presentation request, including:- For each source credential, a primary
eq_proof
of the issuer signature across all of the claims in the credentials. - For each source credential that is revocable and for which the verifier
has requested proof of non-revocation, a non-revocation proof,
non_revoc_proof
.- See the specification section on non-revocation-proof generation for details on this data structure.
- For each requested predicate, a primary
ge_proof
(predicate) proof based on the requested claim from a source credential, the boolean operator (one of<=, <, >, >=
), and the comparison value in the presentation request predicate. - One aggregate proof,
aggregated_proof
, across all of the source credentials that proves that the same link secret was used in the issuance of all of the credentials. - The mapping from each of the requested attributes and predicates to the
primary proofs that satisfies the request.
- A mapping for the requested attributes of the
raw
andencoded
values from each revealed source credential claim. - A list of the self-attested attributes provided for the requested attributes that permit self-attested attributes.
- A list of the unrevealed attributes.
- A mapping of the requested predicates to the
ge_proof
that satisfies the request.
- A mapping for the requested attributes of the
- An array
identifiers
containing theschemaId
andcredDefId
for each source credential in the presentation.- Also included for each source credentials for which a non-revocation proof
is provided is the
revRegDefId
and thetimestamp
of the Revocation Registry Entry used in the non-revocation proof.
- Also included for each source credentials for which a non-revocation proof
is provided is the
- For each source credential, a primary
The following is an example of a multi-credential presentation without revocation.
Replace this example with one that includes:
- two request attributes
- one predicate request
- one unrevealed attribute
- one self-attested attribute
{
"presentation_request": {
"nonce": "182453895158932070575246",
"name": "Step 3 Send your Health Information",
"version": "1.0",
"requested_attributes": {
"biomarker_attrs_0": {
"names": [
"name",
"concentration",
"unit",
"range",
"collected_on",
"biomarker_id",
"researcher_share"
],
"restrictions": [
{
"schema_name": "MYCO Biomarker",
"attr::name::value": "Iron"
}
]
},
"consent_attrs": {
"restrictions": [
{
"schema_name": "MYCO Consent Enablement",
"schema_version": "0.1.0",
"attr::jti_unique_identifier::value": "205b1ea0-7848-48d4-b52b-339122d84f62"
}
],
"name": "jti_unique_identifier"
}
},
"requested_predicates": {}
},
"presentation": {
"proof": {
"proofs": [
{
"primary_proof": {
"eq_proof": {
"revealed_attrs": {
"biomarker_id": "33034450023603237719386825060766757598085121996569112944281451290292212516012",
"collected_on": "92231735610070911075924224447204218356256133056723930517696107260511721601349",
"concentration": "10",
"name": "85547618788485118809771015708850341281587970912661276233439574555663751388073",
"range": "106828626115908025842177441696860557581575579893927923198365300598359723920768",
"researcher_share": "101264834079306301897660576123112461042861436742738894013248454492965796383403",
"unit": "38351211041892038382023569421847544683371072212679556578649761181279472893849"
},
"a_prime": "80156520245352052628208149565161465200964633377479145197038408116901327106468493831807000641577246417448908134495822028339761705905365398613527463662816881507291787145610182891716009505407072490691097943029471835157968113065071523597746984296197661560454442163361095634052138951650373193896962906203169809352467024247772052836999799731422581068645748537557874869718897034120634529002420631012358510111427944993245065350416694516913472010105229188198167306183788520891926236449848811955646933539477960935319919207451858981065765523367984374104834278565184338252025155136368869580505679884921590811310587077071610172673",
"e": "115602723672843258810892161808995599340414281260248127600708536325470178701996999306086286379312077726886107268519700961209712187789855371",
"v": "1250383260306407741656763352595256748825474237767244783206569756476708112785930898966696687140808011529311298553822794830872826226191807175199015541611342880032928005827271961840046208463350458298210749103878893742434685172894883857423865293195542824393317226300133796527531436931435189766065404966370796699897584860421160155369018136946091524266742514828667575397735892093187106092545876795688095293610064164136737808333322708435913545499149948994191514980395955519036106660001526586674248282052492138917987323789012051794441548696998993861159018178474063785171288325900474499496141522583368982451169653258746506425495702762445790848698570457196767532483566475068200091609719957656394696938689265240025099424248587121592521826940348286940172887963179718337593603053496022182071613592070622825622277436966372346642772481567879001423472517233061740522533372490151585309457871632521280719357505751796940152868034526426510835",
"m": {
"master_secret": "3455871040557234123393960708120725061759594951341120214330342075748561632734634451036095543889895409812764789858455375956895105746442946098665140470124325622343440794421325163223",
"client_share": "4233663763294709836704307308997831519311512039775169744174375585917035614714239153287862168426091336550799195245481707264207548331415960277065672755643752404180562900805493953484"
},
"m2": "12942698897200869280316481431207639453433287089474860040781378232999349549981799159560238504559317917040820580596635945161264308025301203452846862479261473387068350544024561412435"
},
"ge_proofs": []
}
},
{
"primary_proof": {
"eq_proof": {
"revealed_attrs": {
"jti_unique_identifier": "46414468020333259158238797309781111434265856695713363124410805958145233348633"
},
"a_prime": "52825780315318905340996188008133401356826233601375100674436798295026172087388431332751168238882607201020021795967828258295811342078457860422414605408183505911891895360825745994390769724939582542658347473498091021796952186290990181881158576706521445646669342676592451422000320708168877298354804819261007033664223006892049856834172427934815827786052257552492013807885418893279908149441273603109213847535482251568996326545234910687135167595657148526602160452192374611721411569543183642580629352619161783646990187905911781524203367796090408992624211661598980626941053749241077719601278347846928693650092940416717449494816",
"e": "40342480172543061520030194979861449480343743039487113094246205723322643070249538229638327935935486373873622430409109409257546971244601965",
"v": "217871997575635857881367472262154388060800564043554848081521162883333745687724235201324121915821236796357195214089699645741515836727882126142579489701412861659136426497703162695983681701205672924385915403141611021784136285588350763399255203187442277784718461565122805239422370067600654500115262174706580098147603414365915243447789285877195068031630371954678432401446457453517813298670236942253026249413255471803997869331683293818651006043399070308083119054618677128448043841313844695654424369871669436628257531643623230026240200330490039607166147891705813033761093730859310423856156850596341547950105490585959768382544221555877471751940512766452511773683786023245283041103270102119125303027835868565240336923422734962345750992898991606841120358203160628015844345063465293475128118937815965000466081345494616126511595974927544434058100817176268040385848789013718618727873445834393897904247054897801708217939187593785671914",
"m": {
"iat_consent_timestamp": "7919242808448912829024078929834347184203169048480606699350973804205285806978474375691141504249426249676222104091995582731720654507393708298132400435805626192291975477967402460279",
"master_secret": "3455871040557234123393960708120725061759594951341120214330342075748561632734634451036095543889895409812764789858455375956895105746442946098665140470124325622343440794421325163223",
"data_controller": "16070549690575784944224634793654539357398383214512772967411296056738507137421264813779497172425030465490587794790393434847583852932544021088761347641812155158324233253206392974293",
"notice": "2790610958721083178459621377821800672322230987466716467063649577108407884592339521820875278264969393963213925568888672412150769438560815981777952572004955362915245795447078373509",
"sensitive": "13552814315985495030467505807226704038231487014593307078913973520081443107274508887651839292151852713782653522711975492131914644109941607616672243509214979259100892541150351227883",
"services": "14860984314279608355643170908802532226194914773406547259519961082467311361623076451869406343140860447342041426195737612897540117192702117380288330928866665314831926780606136352645",
"sub_subject_identifier": "11736177517163751882849070942823049196298287414132249166618760803125435466270948777194044507635346721244111946358927525083691171695431736819244809221351813271261283779276670885101",
"moc_method_of_collection": "10026360820367693771310999595495505533281326977349798360729122862705999157070660881611421445424239119786180921960380892002204780026072600494332540208429642332890963846523547470729",
"jurisdiction_data_processing": "15829143141425514118932461858094583045441924952665872659029333578019676797278419825311275014912077620757631693167948665554731430154156737419706553672424812320891308795411687679270",
"iss_internet_processing_uri": "6900796243066434651671715348976599009606292569990892886896520779618011026060325075822786686418461731663661832508437549373109822105600719490952253743950241384782222356411498407620",
"version_consent_specification": "7796257942256624260327966366702213561879098947042014532961291550019706546662478888172243088973621029223408695289700984802154645011280488167967047321149956253054269901250137513345",
"policy_url": "12241676508867847022708464707584814145889660003604359058532137895063826021524887759921830911553663255421852525705197991376264187781979066233701110706958983099645275940668404311601"
},
"m2": "6509130065158989037891281073557909501783443634141673890142284302459280804904096303151728187237486991775852971807701594247754409108836089746736345158069365449802597798950172729241"
},
"ge_proofs": []
}
}
],
"aggregated_proof": {
"c_hash": "81763443376178433216866153835042672285397553441148068557996780431098922863180",
"c_list": [
[
2,
122,
246,
66,
85,
35,
17,
213,
1
],
[
1,
162,
117,
246,
95,
154,
129,
32
]
]
}
},
"requested_proof": {
"revealed_attrs": {
"consent_attrs": {
"sub_proof_index": 1,
"raw": "205b1ea0-7848-48d4-b52b-339122d84f62",
"encoded": "46414468020333259158238797309781111434265856695713363124410805958145233348633"
}
},
"revealed_attr_groups": {
"biomarker_attrs_0": {
"sub_proof_index": 0,
"values": {
"researcher_share": {
"raw": "bf712cb328a92862b57f0dc806dec12a",
"encoded": "101264834079306301897660576123112461042861436742738894013248454492965796383403"
},
"unit": {
"raw": "μM",
"encoded": "38351211041892038382023569421847544683371072212679556578649761181279472893849"
},
"concentration": {
"raw": "10",
"encoded": "10"
},
"name": {
"raw": "Iron",
"encoded": "85547618788485118809771015708850341281587970912661276233439574555663751388073"
},
"range": {
"raw": "9.00-30.0",
"encoded": "106828626115908025842177441696860557581575579893927923198365300598359723920768"
},
"collected_on": {
"raw": "2020-07-05",
"encoded": "92231735610070911075924224447204218356256133056723930517696107260511721601349"
},
"biomarker_id": {
"raw": "c9ace7dc-0485-4f3f-b466-16a27a80acf1",
"encoded": "33034450023603237719386825060766757598085121996569112944281451290292212516012"
}
}
}
},
"self_attested_attrs": {},
"unrevealed_attrs": {},
"predicates": {}
},
"identifiers": [
{
"schema_id": "CsQY9MGeD3CQP4EyuVFo5m:2:MYCO Biomarker:0.0.3",
"cred_def_id": "CsQY9MGeD3CQP4EyuVFo5m:3:CL:14951:MYCO_Biomarker"
},
{
"schema_id": "FbozHyf7j5q7TDn2s8MXZN:2:MYCO Consent Enablement:0.1.0",
"cred_def_id": "TUku9MDGa7QALbAJX4oAww:3:CL:531757:MYCO_Consent_Enablement"
}
]
}
}
Once the presentation data structure is generated, it is sent to the verifier for processing.
The following describes the data structures listed above, including the process of generating the data of the various types of proofs.
The Presentation Request
The presentation_request
is a copy of the presentation_request
data structure from
the verifier, as described earlier in the specification.
Presentation
The presentation
contains:
- Proofs of the source credentials.
- An aggregated proof across all of the source credentials.
- A mapping of how the requested attributes and predicates are satisfied.
- A list of the identifiers related to each of the source credentials in the proof.
The presentation
data structure is as follows. As noted in the JSON comments
included, details for each section of the presentation
is provided below.
"presentation": {
"proof": {
"proofs": [
{
"primary_proof": {
"eq_proof": {
# Described in detail below
},
"ge_proofs": [
# Described in detail below
]
}
}
],
"aggregated_proof": {
# Described in detail below
}
},
"requested_proof": {
# Described in detail below
}
"identifiers": {
# Described in details below
}
}
The proofs
array contains an entry for each source verifiable credential.
For each is a primary_proof
covering the claims in the source credential called
the eq_proof
, and a ge_proof
for each of the predicate proofs sourced from
the verifiable credential.
Each primary eq_proof
is generated as follows:
To Do: Add algorithm for generating a eq_proof
and the data values in the proof.
Each primary ge_proof
is generated as follows:
To Do: Add algorithm for generating a ge_proof
and the data values in the proof.
The aggregated_proof
proves that the same linked secret was used to
issue all of the source verifiable credentials in the presentation.
The aggregated_proof
is generated as follows:
To Do: Add algorithm for generating the aggregate proof and the data values in the proof.
The requested_proof
is the mapping from the presentation request attributes
and predicates to the data in the presentation that satisfies the request. This
is divided into five parts:
- The request attributes, where a single attribute
name
is requested. - The request attribute groups, where a set of
names
are requested from a single source credential. - Request attributes without
restrictions
that are satisfied with self attested attributes. - Request attributes that are unrevealed.
- Request predicates.
A JSON summary, with comments, for the data in each of the parts is listed below:
Revealed Attributes
An entry for each single name
request attribute from the presentation request.
"revealed_attrs": {
"consent_attrs": { # The request attribute name from the presentation request
"sub_proof_index": 1, # The index of the source credential primary proof for the claim
"raw": "205b1ea0-7848-48d4-b52b-339122d84f62", # The raw and encoded claim values
"encoded": "46414468020333259158238797309781111434265856695713363124410805958145233348633"
}
}
It is important for all verifiers to understand that the revealed attribute
proof (eq_proof
described earlier) is a proof on the encoded
value, not on
the raw
value. As such, it is up to the verifier to know the “raw to encoded”
algorithm used by the issuer, and to verify that the revealed raw
value properly
encodes to the proven encoded
value. It is possible for a malicious holder to
put an unrelated raw
value into a presentation to fool a verifier that does not
checking the encoding process. In most Aries implementations, the encoding is checked
by the Aries framework, as a “post-cryptographic verification” step.
A future version of the AnonCreds specification is likely to do an “on the fly”
encoding in AnonCreds rather than including both values in the source
credentials and presentations. This would prevent the holder from replacing the
raw
value without detection.
Revealed Attribute Groups
An entry for each group names
request attribute from the presentation request.
"revealed_attrs": {
"consent_attrs": { # The request attribute name from the presentation request
"sub_proof_index": 1, # The index of the source credential primary proof for the claims
"values": { # An entry for the each of the names in the request attribute group
"claim_name": { # The name of the claim, its raw and encoded value
"raw": "205b1ea0-7848-48d4-b52b-339122d84f62",
"encoded": "46414468020333259158238797309781111434265856695713363124410805958145233348633"
}
}
}
}
Self Attested Attributes
To Do: Describe self-attested attributes data structure
Unrevealed Attributes
To Do: Describe unrevealed attributes data structure
Predicatees
To Do: Describe predicates data structure
Identifiers
The identifiers
contains a list of the identifiers to be resolved by the
verifier to retrieve the cryptographic material necessary to verify each of the
proofs in the presentation. The identifiers are listed in an array with one
entry per source verifiable credential, ordered by the proofs
list earlier in
the presentation.
The data structure is:
"identifiers": [
{
"schema_id": "CsQY9MGeD3CQP4EyuVFo5m:2:MYCO Biomarker:0.0.3",
"cred_def_id": "CsQY9MGeD3CQP4EyuVFo5m:3:CL:14951:MYCO_Biomarker",
}
]
The example above is for a source credential that is not revocable. For a
revocable source credential, the rev_reg_id
and timestamp
(the identifier
for the Revocation Registry Entry used in the non-revocation proof) are
added. Those are described in the section below on generation of non-revocation
proofs
§ Generate Non-Revocation Proofs
A holder preparing an AnonCreds presentation must determine what, if
any, non-revocation proofs (NRPs) must be included the presentation based on a
combination of what is in the proof request and what verifiable credentials are
to be used in the presentation. As noted in the section on revocation in the
presentation request, the presentation
request may have the non-revoked
item at the outer-most level, applying to all
source credentials, or at the requested_attribute
and/or requested_predicate
level, applying only to specific source credentials. Further, the holder must determine if the source verifiable credential for the requested
attributes/predicates where a NRP is requested is a revocable credential.
Obviously, an NRP cannot be produced for a verifiable credential issued without
that does not support revocation. Where a revocation interval is specified in
the request, and where the source credential to satisfy the request is
revocable, the holder must provide a non-revocation proof.
Once the holder has determined the which source credentials will required an accompanying NRPs in the presentation, the holder must collect and prepare the necessary proof generation inputs.
§ Collecting Data for Generating the Non-Revocation Proof
Recall from the earlier section on preparing inputs to the presentation generation process that for each revocable source credential, the holder must provide the following data elements:
witness
– A single value calculated from the Revocation Registry used by the holder to create the non-revocation proof.timestamp
– Thetimestamp
of the Revocation Registry Entry used by the holder to create the non-revocation proof.timestamp
is an attribute of the Revocation Registry Entry that allows the verifier to uniquely identify the Revocation Registry Entry used by the holder. Thetimestamp
must meet thenon_revocation_interval
requirements specified in the presentation request.
The witness
is an integer that is used in the non-revocation zero
knowledge proof to demonstrate to the verifier that the holder’s credential has
not been revoked. Recall that the accumulator
of a Revocation Registry is the product of the tails file entries for all of the unrevoked
credentials in the registry. For a specific holder, its witness
is the product
of the tails file entries for all of the unrevoked credentials in the registry
except for the holder’s own credential. Obviously, if the witness equals the
accumulator, the holder’s credential has been revoked. But, if not, then a valid
non-revocation proof demonstrates that the witness
times the entry from the tails
file for the holder’s credential equals the accumulator, without revealing
either the witness
, the credential’s index, or its tails file entry.
An AnonCreds process is used to calculate the witness
value, takes the
following inputs:
tails_reader
– A reference to a local copy of the Tails File for the Revocation Registry for reading.revoc_reg_def
– The Revocation Registry Definition, as retrieved from the Verifiable Data Registry to which the issuer published it.rev_status_list
– A data structure about the Revocation Registry to be used for creating the non-revocation proof. It includes:rev_reg_def_id
– the ID of the Revocation Registry Definition.issuer_id
– the ID of the issuer of the source credential and hence, the Revocation Registry Definition.revocation_list
– a bit vector containing the status (revoked
,not revoked
) of all of the credentials in the revocation registryaccum
– the value of the accumulator from the Revocation Registry to be used for creating the non-revocation proof.timestamp
– the value of the timestamp from the Revocation Registry to be used for creating the non-revocation proof.
rev_reg_idx
– The index in the revocation registry of the holder’s credential. This is the credentials for whichrev_state
: An optional, previouswitness
that can be updated to produce the newwitness
output.old_rev_status_list
– An optional, previousrev_status_list
(described above) that was in place at the time the previous witness was generated.
The holder must use the from
and to
timestamp revocation interval
requirements from the presentation request and knowledge of the Revocation Registry Entries to determine which Revocation Registry to retrieve and use in generating the NRP for a given credential. The
selected Revocation Registry Entry must either have been active at the
time of the from
value or have been published by the issuer between the from
and to
values. How to determine an appropriate Revocation Registry to use is up to the holder, and their use of the capabilities of the
relevant Verifiable Data Registry.
::: Note
When Hyperledger Indy is the Verifiable Data Registry for the Revocation Registry Entry, the state is received from Indy ledger as the
“deltas” (state changes) from either the initial state of the Registry or from a
previous Revocation Registry Entry. While the older Indy version of
AnonCreds used the “deltas” representation directly, the newer AnonCreds version
requires that the holder software convert the Indy “deltas” format into the
rev_status_list
representation, with every credential in the registry is given
a revoked
or not revoked
boolean value.
The benefit of the “full state” representation for Revocation Registry is that the :Verifiable Data Registry can be “dumb”, returning the same static file given to it by the Issuer. With the Indy “deltas” approach, the [[Verifiable Data Registry (VDR)]] must be an active service returning an on-the-fly calculated result based on the inputs of the holder’s request.
:::
In collecting the revocation_list
data in the rev_status_list
, the holder
may discover that their credential has been revoked by the issuer. The holder
may choose at that point to stop the presentation process. If the holder decides
to proceed, they will not be able to create a valid non-revocation proof for the
source credential.
The output of the process is the new witness
for a credential that will be
used as input to the generate presentation process.
§ Non-Revocation Proof Generation Steps
Given the data collected by the holder to produce the NRP, the following calculations are performed.
Once the witness (u
), the accumulator from the ledger (e
) and the value of
the tails file entry for the credential of interest (b
) are known, the NRP can
be generated as follows:
To Do: Add more detail about the calculation of C
u
and
C
b
in the following.
- The holder calculates
u*b = e
, where e is the accumulator. - The holder derives two values (in cryptograhic terms -
commitments)
C
u
andC
b
based onu
andb
. - The holder then calculates
T
fromC
u
andC
b
and sends all three to the verifier. - The verifier uses
e
(the accumulator from the ledger),C
u
andC
b
to calculate its ownT'
and confirms thatT
andT'
are the same.
This is the zero knowledge non-revocation proof.
Each NRP is added alongside the credential to which the NRP is applied, to the presentation generated by the holder using this data model:
"non_revoc_proof": {
"x_list": {
"rho": "...",
"r": "...",
"r_prime": "...",
"r_prime_prime": "...",
"r_prime_prime_prime": "...",
"o": "...",
"o_prime": "...",
"m": "...",
"m_prime": "...",
"t": "...",
"t_prime": "...",
"m2": "...",
"s": "...",
"c": "..."
},
"c_list": {
"e": "...",
"d": "...",
"a": "...",
"g": "...",
"w": "...",
"s": "...",
"u": "..."
}
}
The values in the data model are:
To Do: Enumerate each of the items in each NRP section of the presentation.
x_list
" is …rho
" is …r
" is …r_prime
" is …r_prime_prime
" is …r_prime_prime_prime
" is …o
" is …o_prime
" is …m
" is …m_prime
" is …t
" is …t_prime
" is …m2
" is …s
" is …c
" is …
c_list
" is …e
" is …d
" is …a
" is …g
" is …w
" is …s
" is …u
" is …
As well, in the presentation data model, added to the identifiers
item, is the
timestamp (Unix epoch format) of the RevRegEntry used to construct the NRP
(see example below). The verifier needs the rev_reg_id
and timestamp
to get
the correct accumulator to use in verifying the NRP.
"identifiers": [
{
"schema_id": "7BPMqYgYLQni258J8JPS8K:2:degree schema:46.58.87",
"cred_def_id": "7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema",
"rev_reg_id": "7BPMqYgYLQni258J8JPS8K:4:7BPMqYgYLQni258J8JPS8K:3:CL:70:faber.agent.degree_schema:CL_ACCUM:61d5a381-30be-4120-9307-b150b49c203c",
"timestamp": 1656269796
}
]
In step 6 of the AnonCreds Presentation Data Flow, the holder sends the verifiable presentation, including any embedded NRPs, to the verifier.
Link: indy-anoncreds/docs/dev/anoncred.pdf
§ Verify Presentation
In step 7, 8, and 9 of the AnonCreds Presentation Data Flow, the Verifier collects the required information and verifies the verifiable presentation and accepts it if the signature is valid, otherwise rejects the verifiable presentation.
This section covers the overall verification process of the attributes, predicates and link secret. Following that is a section that specifies the process for verifying the non-revocation proofs (if any) in the presentation.
pub extern fn anoncreds_verifier_verify_proof(command_handle: CommandHandle,
proof_request_json: *const c_char,
proof_json: *const c_char,
schemas_json: *const c_char,
credential_defs_json: *const c_char,
rev_reg_defs_json: *const c_char,
rev_regs_json: *const c_char,
cb: Option<extern fn(command_handle_: CommandHandle, err: ErrorCode,
valid: bool)>) -> ErrorCode {}
-
proof_request_json
: Proof request in JSON format. -
proof_json
: Proof for the given proof request. -
schemas_json
: Collection of all schemas participating in the proof. -
credential_defs_json
: Collection of all credential definitions participating in the proof. -
rev_reg_defs_json
: Collection of all revocation registry definitions participating in the proof.{ "rev_reg_def1_id": <rev_reg_def1>, "rev_reg_def2_id": <rev_reg_def2>, "rev_reg_def3_id": <rev_reg_def3>, }
rev_regs_json
: Collection of all revocation registries participating in the proof.{ "rev_reg_def1_id": { "timestamp1": <rev_reg1>, "timestamp2": <rev_reg2>, }, "rev_reg_def2_id": { "timestamp3": <rev_reg3> }, "rev_reg_def3_id": { "timestamp4": <rev_reg4> }, }
cb
: Callback that takes command result as parameter.Returns
valid
: true - if signature is valid, false - otherwise
§ Verify Non-Revocation Proof
If the presentation includes one or more Non-Revocation Proofs (NRPs) the verifier must also extract from the verifiable presentation the NRPs and process each proof. If any of the NRPs cannot be verified because one or more of the attributes/predicates came from a revoked credential, the overall status of the presentation is rejected – not verifiable. The following outlines the process for verifying an NRP.
The verifier begins by extracting from the section of the presentation
for a given revocable credential the non_revoc_proof
and identifiers
data
items. The verifier must retrieve (possibly from its cache, otherwise
from the VDR) the published RevRegEntry given the rev_reg_id
and timestamp
values from the identifiers
data item. The verifier
extracts the accumulator
item from the RevRegEntry retrieved. Note
that the verifier does not need to collect the revocation status of all
of the credentials in the registry, nor the contents of the tails file for the
RevReg. Only the issuer and holder needs that data. During the
verification process, the verifier does not learn the index of the
holder's credential in the RevReg.
Once the verifier gets the data in the non_revoc_proof
data item from
the presentation for the NRP being processed, plus the accumulator from
appropriate RevRegEntry, the following steps are carried out to verify
the NRP.
To Do: Outline the NRP verification calculation.
To Do: Is there a separate process to bind the NRP to the credential?
The verification code MUST surface to the verifier if any part of the presentation, including any NRP(s), fail cryptographic verification. The verification code MAY surface additional detail about what part of the presentation failed, such as which NRP failed verification (if any).
The verifier SHOULD evaluate the presentation to make sure that the holder provided all requested NRPs. Notably, if any expected NRPs are not received in the presentation, the verifier SHOULD check to see if the given credential type is revocable. If not, it is acceptable that no NRP was received. However, if the credential used in the generation of the proof is revocable, and the holder did not provide the NRP, the verification code SHOULD surface to the verifier that the presentation failed cryptographic verification.
§ AnonCreds Revocation Data Flow
AnonCreds includes a mechanism that supports the revocation of verifiable credentials. This mechanism includes:
- An issuer setting up to issue revocable credentials.
- An issuer issuing revocable credentials.
- An issuer activating or revoking issued credentials.
- A verifier requesting a presentation to include a non-revocation proof for one or more revocable credentials.
- A holder generating based on the presentation request of the verifier a non-revocation proof for attributes derived from revocable credentials.
- A verifier verifying a non-revocation proof included in a presentation from a holder.
A fundamental goal of AnonCreds is to not provide a correlatable identifier for either a holder or a credential as part of generation and verification of an AnonCreds presentation. Applying that goal to revocation means that the revocation mechanism must support the holder proving a credential used in generating a presentation is not revoked without providing a correlatable identifier for that credential or the holder itself. As such, the AnonCreds revocation mechanism uses a Zero Knowledge Proof (ZKP) that allows the holder to prove a credential they hold is not revoked without revealing an identifier for their credential or the holder.
§ AnonCreds Issuer Setup With Revocation
The details of issuer setting up revokable credential types are covered
in the issuer setup
section of this specification. Note the warning and recommendation against the
use of ISSUANCE_ON_DEMAND
in that part
of the specification.
§ AnonCreds Issuance with Revocation
The details of an issuer issuing a revokable credential to a holder are covered in the issuance data flow section of this specification.
§ AnonCreds Credential Activation/Revocation and Publication
When an issuer decides to revoke a previously issued credential (or activate a previously inactive/revoked credential), they do so by publishing another instance of the RevRegEntry object. Recall from the issuer setup section, the specification about RevRegEntry[creating and publishing the first RevRegEntry](data_flow_setup.md#creating-the-initial-revocation-registry-entry-object) for a RevReg. In that process, the accumulator for the initial state of the RevReg is published. When subsequent RevRegEntry transactions are published to the ledger, each includes an updated value of the accumulator. The update of the accumulator is necessary with each revocation or (re)activation of a credential or set of credentials since the last published RevRegEntry. This is because only the factors (all factors are listed in the respective tails file) of credentials which are active (meaning not being revoked) contribute to the accumulator. Therefore in addition to the updated accumulator value, every RevRegEntry contains lists of indices of credential factors which have been either revoked or (re)activated within the RevRegEntry. This list of factor indices is a so called Witness and enables the Holder to successfully generate a proof of non revocation.
An example of the data in the RevRegEntry is shown in the following example of a RevRegEntry, pulled from this transaction on the Sovrin MainNet.
"data": {
"revocDefType": "CL_ACCUM",
"revocRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960",
"value": {
"accum": "21 116...567",
"prevAccum": "21 128...C3B",
"issued": [
],
"revoked": [
172
]
}
},
In the above:
revocDefType
: is defined by the comparable entry in the RevReg, and for this version of AnonCreds is hard-coded toCL_ACCUM
.revocRegDefId
: is the Id of the RevReg to which this entry is being added.accum
: is the new value of the accumulator based on the state of the credentials in the RevReg, including those listed in this transaction. The value is calculated by the Issuer based on the credential state changes, and submitted as part of the transaction, and verified by the ledger before being published.prevAccum
: is the previous value of the accumulator. The value is supplied by the Issuer in the transaction request, and verified by the ledger before being published.issued
: an array (possibly empty or not supplied) of the indices within the RevReg of the credentials whose state has changed toactive
(also known asnot revoked
) since the last RevRegEntry was published to the ledger.revoked
: an array (possibly empty or not supplied) of the indices within the RevReg of the credentials whose state has changed torevoked
(also known asnot active
) since the last RevRegEntry was published to the ledger.
In the example transaction above no credentials are issued
(meaning changed
from status revoked
to issued
) and only one, the credential with index
172
, is changed to revoked
. Both lists can have an arbitrary number of
entries, up to the total number of credentials in the RevReg.
The algorithm to calculate the value of a RevRegEntry accumulator at any time is the same: determine the (modulo) product of the primes for each non-revoked credential in the Revocation Registry, as described here.
The issuer MUST track of the revocation status of all of the
credentials within a RevReg so that it can both calculate the correct
accumulator and send to the VDR accurate lists (issued
and revoked
)
of the indices of the credentials whose status has changed since the last RevRegEntry was published. If the list and accumulator published to VDR get out of
sync a holder will not be able to generate a valid NRP.
A VDR publishing a RevReg MAY perform its own calculation of the accumulator based on the list updates received in a RevRegEntry transaction to ensure that the calculation of the accumulator after all of the revocation status updates to the credentials within the RevReg have been applied, rejecting the transaction if the calculated accumulator does not match that from the issuer.
If an issuer's local revocation information gets out of sync with what is in the VDR, the issuer MUST rationalize the differences and produce a RevRegEntry transaction that accounts for both the last published RevRegEntry published in the VDR and the desired revocation status of all of the credentials in the RevReg.
The holder is not involved in the process of revoking a credential. There is no technical requirement for an issuer to notify the holder that a credential they were issued has been revoked. That said, it is a courtesy that may improve the user experience of the holder. Aries RFC 0183 Revocation Notification is an example of how that can be done. Even if not notified by the issuer of the revocation of a credential, the holder can detect their credential has been revoked when they retrieve the list of revoked credentials from the VDR and discover the index of their credential in the list.
§ AnonCreds Presentation Request with Revocation
Carrying out an AnonCreds presentation with revocation is a two-step process, beginning with a request from the verifier asking the holder to include a non-revocation proof (NRP) in the presentation, and then the holder creating the NRP and including it in the presentation sent to the verifier.
The verifier requesting a non-revocation proof, and the holder generating the non-revocation proof are covered in the sections of this specification about requesting and generating presentations, respectively.
§ AnonCreds Verification with Revocation
A verifier receives the presentation from the holder and processes the non-revocation-related parts of the presentation and the revocation-related parts of the presentation (if any) in the presentation. The resulting status of the presentation combines the verification outcomes from processing all proofs within the presentation. If verification of one or more of the embedded proofs is unsuccessful, the presentation is rejected as unverifiable.
§ AnonCreds Methods
In the AnonCreds data flows are specifications of data models that contain identifiers to public AnonCreds objects (Schemas, CredDefs, Revocation Registry Definitions and Rev_Reg_Entrys) that are published by issuers to locations (Verifiable Data Registries or VDRs) that must be accessible to holders and verifiers to enable presentation generation and verification. The format of the objects identifiers and the location of the objects are not defined in this specification. Rather, similar to the approach of DID Methods defined in the W3C DID Specification, AnonCreds methods allow for the registration and resolution mechanisms for AnonCreds objects across a range of VDRs. A registry of supported AnonCreds methods can be found in the AnonCreds Methods Registry.
Each AnonCreds method specifies the format of the object identifiers, to what Verifiable Data Registry the objects are published, how issuers register (publish) objects, and how issuers and verifiers can resolve the identifiers to retrieve the published objects. Implementations of agents (issuers, holders, verifiers) with AnonCreds support should be organized so as to allow issuers to use at least one AnonCreds method for registration, and to allow holders and verifiers to use one or more AnonCreds Methods for resolution. AnonCreds issuers will likely choose just a single AnonCreds registration method(s) they will use, and all AnonCreds participants will choose the set of AnonCreds resolvers they will require based on the issuers and types of credentials they want to support. As with DIDs, an external Universal AnonCreds Resolver is possible, as is a Universal AnonCreds Registrar.
§ AnonCreds Identifiers
AnonCreds identifiers MUST be a Uniform Resource Identifier (URI)
conformant with RFC3986, although
one notable exception is permitted. The exception is that for backwards
compatibility, the AnonCreds identifiers used in the early (pre
did:indy
) open source Hyperledger Indy AnonCreds implementation are permitted.
In the AnonCreds Method Registry,
this is the Hyperledger Indy Legacy AnonCreds Method.
§ Issuer Identifiers
All AnonCreds objects that are published to a Verifiable Data Registry (Schema, Credential Definition, Revocation Registry Definition, and Revocation Status List) contain an issuerId
reference. This identifier references the creator (issuer) of the specific AnonCreds object.
AnonCreds identifiers MUST be a Uniform Resource Identifier (URI)
conformant with RFC3986, although
one notable exception is permitted. The exception is that for backwards
compatibility, the Indy DIDs used in the early (pre did:indy
) open source
Hyperledger Indy implementation are permitted.
An AnonCreds object issuer identifier MAY be publicly resolvable. AnonCreds methods MUST define the format of the issuer identifier, and MUST verify that the publisher of the AnonCreds object controls the issuer identifier before publishing the object.
§ Revocation Support
Implementers only familiar with the “deltas”-style data format of Hyperledger Indy RevRegEntries may not be aware that other VDRs may store the contents of each RevRegEntry as “full state”, meaning the status of each credential in the registry (revoked or not) is stored, vs. only the differences from the previous RevRegEntry as in Hyperledger Indy. Either approach is fine as long as data is normalized by the AnonCreds method to the RevReg format expected for AnonCreds generate presentation processing. This allows a AnonCreds Methods to trade-off the size of the RevRegEntry in the VDR with the need for VDR-side processing to collect all of the deltas needed by the holder.
An AnonCreds Method may opt to not support revocation at all, and generate an error if the issuer attempts to create a CredDef that includes revocation support.
§ AnonCreds Method Registry
The AnonCreds Method Registry is published here. The registry contains a description, metadata and a link to a specification for each AnonCreds Method submitted by its implementers/maintainers. The registry is a web page generated from this repository.
The AnonCreds Methods registry repository and published registry is managed by the AnonCreds Specification Working Group based on this governance framework.
Each entry in the AnonCreds Method Registry links to a specification for the associated AnonCreds objects method. The method specifications must include information about the AnonCreds identifiers used by the method, along with the mechanisms for AnonCreds objects registration and resolution. In some cases, the AnonCreds method specification is defined within a DID Method specification, while in other cases, the AnonCreds method is a standalone specification.
§ Cryptographic protocols
§ Terminology
TODO: general terms here
- We use
PRNG(size)
to reference an invocation of a cryptographically secure pseudo-random number generator requiring the generation of a random integer in the range[0, size-1]
. Alternatively we usePRNG(min, max)
to refer to the generation of a random integer in the range[min, max]
.
§ Protocols
Most protocols described here are zero-knowledge proofs for different statements. They follow the patterns of three-move rounds protocols with a commit, a challenge and a response phase which we shall describe as three separate algorithms. The challenge phase is unique, whereas the commit and response phases have a specific instance for each of the statements being proved.
§ Issuer Setup
The issuer setup consists of a set of algorithms to generate the Issuer Public Key. The set of algorithms are:
CredentialKeyGen
is used by the Issuer to generate the credential public/private keypair.RevocationKeyGen
is used by the Issuer to generate the revocation public/private keypair.
The reference implementation of CredentialKeyGen
is here.
( PK, SK ) = CredentialKeyGen( L )
Inputs:
- L, the total number of attributes signed by this issuer
Parameters:
-
Definitions:
- l_n, the bitlength of the RSA modulus n of the issuer public key
Outputs:
- PK, the credential public key of the issuer
- SK, the credential secret key of the issuer
Procedure:
1. p = SafePrime(l_n/2) # Generate a safe prime
2. q = SafePrime(l_n/2) # Generate a safe prime
3. n = p * q # The RSA modulus
4. p' = (p-1)/2 # The Sophie Germain prime of p
5. q' = (q-1)/2 # The Sophie Germain prime of q
6. S = PRNG(l_n)^2 (mod n) # A quadratic residue mod n, it generates the subgroup mod n of size p' * q'
7. Z = S^{PRNG(2, p'*q' - 1)} (mod n) # The term Z of the CL public key
8. R = () # Initialise the set of terms R_i of the CL public key
9. foreach j in (1, ..., L):
10. R = R + {S^{PRNG(2, p'*q' - 1)} (mod n)} # Generate R_j
11. PK = ( n, S, Z, R )
12. SK = ( p, q )
13. return ( PK, SK )
§ Proving knowledge of a signature with selective disclosure of messages (ProveCL
)
ProveCLCommit
and ProveCLResponse
are used by a Holder who possesses one or more signatures from one or more Issuers and uses them to derive a proof of knowledge for them. The algorithms are invoked once per signature.
TODO: considerations about the algorithm and its security
TODO: clarify exact format and encoding of inputs and outputs
The reference implementation of ProveCLCommit
is here.
( A', v', e', Z~, e~, v~ ) = ProveCLCommit( PK, signature, (m_1,..., m_L), RevealedIndexes, R )
Inputs:
- PK (REQUIRED), the public key of the issuer
- signature (REQUIRED), the output of the issuance protocol
- (m_1,..., m_L) (OPTIONAL), the set of signed messages
- RevealedIndexes (OPTIONAL), indices of revealed messages
- R (OPTIONAL), the set of random factors to blind unrevealed messages; each random has length l_m + l_0 + l_H
Parameters:
- TBD
Definitions:
- l_n, the bitlength of the RSA modulus n of the issuer public key
- l_m, the bitlength of messages
- l_e, the bitlength of the prime e
- l_v, the bitlength of the randomization factor v
- l'_e, the size of the interval in which e is chosen
- l_0, security parameter that governs the statistical zero-knowledge property
- l_H, the bitsize of values hashed by the hash function H used for the Fiat-Shamir heuristic
- L, the number of messages signed by the issuer
Outputs:
- A', term of the rerandomised signature
- v', term of the rerandomised signature
- e', term of the rerandomised signature
- Z~. t-value for the signature
- e~, randomness used to generate t-value
- v~, randomness used to generate t-value
Procedure:
1. (i1, i2,..., iR) = RevealedIndexes # the indices of messages that are revealed in this proof
2. (j1, j2,..., jU) = [L] \ RevealedIndexes # the indices of messages that are kept hidden
3. (m~_1, m~_2,..., m~_U) = R # the random factors blinding each hidden message
4. (n, S, Z, R_1, ..., R_L) = PK # unpack the issuer public key
5. (A, e, v) = signature # unpack the signature
6. r = PRNG(l_n + l_0) # choose random to blind the signature
7. A' = A * S^r mod n # compute the randomised signature
8. v' = v - e * r # recompute v given the randomisation
9. e' = e - 2^{l_e - 1} # prepare value to prove that e is positive
10. e~ = PRNG(l'_e + l_0 + l_H) # random for t-value of the signature
11. v~ = PRNG(l_v + l_0 + l_H) # random for t-value of the signature
12. Z~ = A'^{e~} * S^{v~} mod n # compute t-value for the signature
13. foreach j in (j1, j2,..., jU):
14. Z~ = Z~ * R_j^{m~_j} mod n # add component for each undisclosed message
15. return ( A', v', e', Z~, e~, v~ )
The reference implementation of ProveCLResponse
is here.
pi = ProveCLResponse( (m_1,..., m_L), RevealedIndexes, R, c, ( A', v', e', Z~, e~, v~ ) )
Inputs:
- (m_1,..., m_L) (OPTIONAL), the set of signed messages
- R (OPTIONAL), the set of random factors to blind unrevealed messages; each random has length l_m + l_0 + l_H
- c, an octet string representing the Fiat-Shamir challenge value
- A', term of the rerandomised signature
- v', term of the rerandomised signature
- e', term of the rerandomised signature
- Z~. t-value for the signature
- e~, randomness used to generate t-value
- v~, randomness used to generate t-value
Parameters:
- TBD
Definitions:
- TBD
Outputs:
- A', term of the rerandomised signature
- Z~. t-value for the signature
- e^, s-value for the signature
- v^, s-value for the signature
- (m^_1,..., m^_L), s-value for the signature
Procedure:
1. (j1, j2,..., jU) = [L] \ RevealedIndexes # the indices of messages that are kept hidden
2. (m~_1, m~_2,..., m~_U) = R # the random factors blinding each hidden message
3. v^ = v~ + c * v' # the response for the term v'
4. e^ = e~ + c * e' # the response for the term e'
5. foreach j in (j1, j2,..., jU):
6. m^_j = m~_j + c * m_j # the response for the undisclosed messages
7. pi = (A', Z~, e^, v^, (m^_1,..., m^_L) ) # the terms that constitute the proof that will be verified
8. return pi
§ AnonCreds Conventions
Cover conventions like encoding claims, date handling for predicates and revocation status requests
§ IANA Considerations
This document has no IANA actions.
§ Security Considerations
§ Cryptography
§ Signature
Add security considerations related to CL signatures
§ Revocation / Accumulators
Add security considerations related to cryptographic accumulators and AnonCreds revocation
- issues with too small revocation registries
- …
§ Verifiable Data Registry
It is recommended to use a Verifiable Data Registry that complies with the state of the art security features and best practices.
§ Permission Management
The VDR for storing Schemas, Credential Definitions, Revocation Registry Definitions, and Revocation Status Lists shall ensure that only the owner or from the owner permitted entities can write, edit, or revoke those AnonCreds objects. Furthermore, public AnonCreds objects shall be readable by any entity that can access the VDR.
§ Authentication of Issuer
The VDR shall allow only permitted entities to issue AnonCreds based on AnonCreds objects related to it.
§ Security Requirements at DIDs and Related Keys
It is recommended to follow the best practices of decentralized key management system designs and architectures. For example, an option for publishing AnonCreds is the Hyperledger Indy, which are built on the following DKMS Design and Architecture
§ Envelope
AnonCreds should be packed in a message envelope that can fulfill properties such as authenticity, integrity, confidentiality, and non-repudiation of the message. A message can have these properties with signature and encryption algorithms. It is recommended to choose signature and encryption algorithms that are state of the art and offer such security. For example, Hyperledger Indy utilizes DIDComm v1 as message envelope for exchanging AnonCreds between issuers, holders, and verifiers.
§ Transport
This specification does not mention which transport protocols should be used to exchange AnonCreds between parties. It is recommended to use transport protocols that are state of the art and offer such security.
§ Wallet
It is recommended to follow the wallet security best practices such as the one created by the [DIF Wallet Security Working Group] (https://github.com/decentralized-identity/wallet-security)
§ Recovery
The wallets for AnonCreds shall offer recovery mechanisms for the holders to export their keys and/or link secrets to different devices. Furthermore, wallet applications should offer portability mechanisms for holders to migrate their credentials from one wallet (or end device) to another.
§ Support of Hardware Secure Modules
The current underlying signature algorithm of AnonCreds is currently not supported by any hardware secure module. Use cases requiring binding of an AnonCreds to a device (device binding) can follow the best practices of wallet security (hyperlink) until the AnonCreds signature algorithm is supported by hardware secure modules of enduser devices.
§ Crypto Agility
The underlying signature algorithm of AnonCreds is not known to be a post-quantum computing resistant. As new signature algorithms evolve for the post-quantum computing security, the underlying signature algorithm of AnonCreds shall keep privacy-preserving features such as selective disclosure and non-correlatability.
§ Privacy Considerations
Add privacy considerations.
§ References
§ Normative References
Add normative references
§ Informative References
Add informative references
§ Resources on cryptography
§ Sigma protocols
- The original work by Schnorr
- Cramer’s thesis that first defines the concept of Sigma protocol
- set of lecture notes on Sigma protocols
- book with a section on sigma protocols
- Blog post on Zero Knowledge Proofs with Sigma Protocols
§ Acknowledgements
AnonCreds was initially created as part of the Open Source Hyperledger Indy project.
This specification is the work of the AnonCreds Working Group, which includes dozens of active and dedicated participants. In particular, the following individuals contributed ideas, feedback, and wording that influenced this specification:
- Artur Philipp - Technische Universität Berlin, IDUnion
- Hakan Yildiz - Technische Universität Berlin
- Matt Raffel - Kiva Microfiance
§ Authors’ Addresses
Add authors’ addresses.