├── .github └── workflows │ └── render-specs.yml ├── .gitignore ├── .vscode └── settings.json ├── 1._Community_Specification_License-v1.md ├── 2._Scope.md ├── 3._Notices.md ├── 4._License.md ├── 5._Governance.md ├── 6._Contributing.md ├── 8._Code_of_Conduct.md ├── EditingTheSpec.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── SECURITY.md ├── assets ├── compiled │ ├── body.js │ ├── head.css │ ├── head.js │ └── refs.json ├── css │ ├── chart.css │ ├── custom-elements.css │ ├── index.css │ └── prism.css ├── icons.svg └── js │ ├── chart.js │ ├── custom-elements.js │ ├── font-awesome.js │ ├── index.js │ ├── markdown-it.js │ ├── mermaid.js │ ├── popper.js │ ├── prism.js │ ├── tippy.js │ └── utils.js ├── custom-assets ├── custom-body.js ├── custom-head.js └── custom.css ├── data ├── MutiCredentialPresentation.json ├── W3CCredential.json ├── W3CCredentialWithRevocation.json ├── W3CPresentation.json ├── W3CPresentationWithRevocation.json └── anoncreds-w3c-context.json ├── docs └── .gitignore ├── gulpfile.js ├── index.js ├── package-lock.json ├── package.json ├── spec ├── abstract.md ├── acknowledgements_authors.md ├── anoncreds_conventions.md ├── anoncreds_methods.md ├── data_flow_issuance.md ├── data_flow_presentation_create_presentation.md ├── data_flow_presentation_create_request.md ├── data_flow_presentation_overview.md ├── data_flow_presentation_verify.md ├── data_flow_revocation.md ├── data_flow_setup.md ├── diagrams │ ├── anoncreds-visual-data-model-overview-simple-trust-triangle.png │ ├── anoncreds-visual-data-model-overview-simple-trust-triangle.pptx │ ├── anoncreds-visual-data-model-overview-simple.drawio │ ├── anoncreds-visual-data-model-overview-simple.png │ ├── anoncreds-visual-data-model-overview.drawio │ └── setup-workflow.puml ├── header.md ├── iana_considerations.md ├── images │ ├── README.md │ └── logo │ │ ├── hl_anoncreds_black.png │ │ ├── hl_anoncreds_black.svg │ │ ├── hl_anoncreds_colour.png │ │ ├── hl_anoncreds_colour.svg │ │ ├── hl_anoncreds_white.png │ │ └── hl_anoncreds_white.svg ├── informative_references.md ├── introduction.md ├── normative_references.md ├── privacy_considerations.md ├── requirements_notations_conventions.md ├── security_considerations.md ├── status_copyright_toc.md ├── terminology.md ├── ursaAnonCreds.pdf └── w3c_representation.md ├── specs.json └── src ├── asset-map.json └── markdown-it-extensions.js /.github/workflows/render-specs.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Build Spec 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | workflow_dispatch: 9 | push: 10 | branches: 11 | - main 12 | 13 | jobs: 14 | build_spec: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 🛎️ 18 | uses: actions/checkout@v2 19 | with: 20 | persist-credentials: false 21 | 22 | - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. 23 | run: | 24 | npm install 25 | npm run render 26 | 27 | - name: Override gitignore 28 | run: git add -f docs/index.html 29 | 30 | - name: Deploy 🚀 31 | uses: JamesIves/github-pages-deploy-action@4.1.3 32 | with: 33 | token: ${{ secrets.GITHUB_TOKEN }} 34 | branch: gh-pages # The branch the action should deploy to. 35 | folder: . # The folder the action should deploy. 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | .idea 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Netbeans 107 | nbproject/ 108 | 109 | # VSCode 110 | .vscode/ 111 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "accum", 4 | "anoncreds" 5 | ], 6 | "liveServer.settings.port": 5501 7 | } 8 | -------------------------------------------------------------------------------- /2._Scope.md: -------------------------------------------------------------------------------- 1 | # Scope 2 | 3 | This document outlines the scope of work undertaken by the AnonCreds Open Specification Working Group. 4 | 5 | ## Objectives 6 | 7 | The objective of this Working Group is to document the existing AnonCreds de facto standard as the initial AnonCreds v1.0 Specification and put the specification on a standards track. Once the work on defining the initial specification is sufficiently far along, the Working Group will develop additional versions of the specification evolving from the initial specification. 8 | 9 | ### v1.0 10 | 11 | The AnonCreds v1.0 Specification provides, as a main difference to v0.1, the decoupling from the Indy ledger. It aims at being entirely ledger-agnostic. Non-goals of this version are changes to the CL signatures signing algorithm in the sense that this will remain the single supported cryptographic signature suite. 12 | 13 | ### v2.x 14 | 15 | Tentatively (this is subject to change in the the future, before an actual release of a v2.x spec), the v2.x will additionally aim at being crypto-agnostic. This entails integrating e.g. BBS+ signatures as an alternative to CL signatures. Eventually, the user should be able to choose which signing algorithms they prefer to use. 16 | 17 | ## Background/Context 18 | 19 | Since 2017, many organizations across the globe have been implementing verifiable credential-based solutions using the AnonCreds (Anonymous Credentials) implementation that was built into the Hyperledger Indy open source project. AnonCreds provides capabilities that many see as important for digital identity use cases in particular, and verifiable data in general. These features include: 20 | 21 | - A full implementation of the Layer 3 verifiable credential “Trust Triangle” of the [Trust over IP Model](https://trustoverip.org/wp-content/toip-model/). 22 | - Complete flows for issuing verifiable credentials (Issuer to Holder), and requesting, generating and verifying presentations of verifiable claims (Holder to Verifier) as well as revocation capabilities. 23 | - Fully defined data models for all of the objects in the flows, including verifiable credentials, presentation requests and presentations sourced from multiple credentials. 24 | - Fully defined applications of cryptographic primitives. 25 | - 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: 26 | - Blinding issuer signatures to prevent correlation based on those signatures. 27 | - The use of unrevealed identifiers for holder binding to prevent correlation based on such identifiers. 28 | - The use of predicate proofs to reduce the sharing of PII and potentially correlating data, especially dates (birth, credential issuance/expiry, etc.). 29 | - A revocation scheme that proves a presentation is based on credentials that have not been revoked by the issuers without revealing correlatable revocation identifiers. 30 | 31 | While AnonCreds is open source and has become a de facto standard, it is not an open specification. Some in the larger self-sovereign identity community view AnonCreds as proprietary. Others are concerned that it is only open source, and subject to change by any code maintainer. The focus of this Working Group is to make AnonCreds an open specification and remove those barriers to broader adoption. As well, unsuccessful attempts have been made to align AnonCreds with the W3C Verifiable Credential Data Model v1.x, larger because of some core differences in the two approaches to verifiable credentials. 32 | 33 | Initial work of the group will focus on putting into specification form the existing implementation of AnonCreds as found in the two existing Indy implementations. Part of that work will be the removal of all dependencies in the specification on the remote storage of objects, including Hyperledger Indy ledger. There is no technical requirement to require Indy in implementing AnonCreds, although there may be some identifiers that may have to be renamed because of Indy-isms in the identifiers. 34 | 35 | Subsequent work will be on a new AnonCreds specification that has the goal of keeping the capabilities of the current AnonCreds, while updating the underlying primitives, such as replacing CL-Signatures with BBS+ Signatures and defining a more scalable revocation scheme. To be determined by the working group is whether and how the standard might produce artifacts that align with the in-process W3C VC v2.0 data model standard. 36 | 37 | ## Membership and Joining 38 | 39 | This specification is being developed under the [Community Specification 1.0 License](https://github.com/CommunitySpecification/1.0/1._Community_Specification_License-v1.md). Contributors to this specification must adhere to the license, as outlined in the repository’s [license file](/4._License.md) file. 40 | 41 | ## Deliverables 42 | 43 | 1. AnonCreds Specification v0.1 — matching the existing Indy-specific AnonCreds implementations exactly. 44 | 1. The AnonCreds Specification Working Group has de-emphasized this version and is focused on the v1.0 specification. The v0.1 MAY be published after the v1.0 specification is complete, if the Working Group feels there is value in doing that. 45 | 2. AnonCreds Specification v1.0 — matching the existing AnonCreds implementations, agnostic to the Verifiable Data Registry (VDR) used for the storage of published AnonCreds objects, and in a format suitable for a selected Standards Developing Organization. 46 | 3. Future AnonCreds Specification versions — evolutions from AnonCreds Specification v1.0. 47 | 48 | - Link to GitHub repository: [https://github.com/hyperledger/anoncreds-spec](https://github.com/hyperledger/anoncreds-spec) 49 | - Link to Draft specification: [https://hyperledger.github.io/anoncreds-spec](https://hyperledger.github.io/anoncreds-spec) 50 | 51 | ## Milestones 52 | 53 | Key milestones will include, but are not limited to: 54 | 55 | 1. Publication of the first Draft AnonCreds v1.0 Deliverable from a generated GitHub repository. 56 | 2. Publication of the final Draft AnonCreds v1.0 Deliverable. 57 | 3. Approval of the Draft AnonCreds v1.0 Deliverable as a Working Group Approved Deliverable. 58 | 4. Optional: Publication of the AnonCreds v0.1 Deliverable from a generated GitHub repository. 59 | 5. The placement of the AnonCreds v1.0 Specification on the standards track of an SDO. 60 | 6. Repeat steps 2-4, 5 for AnonCreds v2.0 Specification. 61 | 62 | ## Dependencies 63 | 64 | - The AnonCreds v0.1 specification MUST align with AnonCreds open source implementations in Hyperledger Indy (indy-sdk, indy-shared-rs repos). 65 | - The AnonCreds v1.0 MUST align with the existing AnonCreds open source implementations in Hyperledger AnonCreds ([anoncreds-rs](https://github.com/hyperledger/anoncreds-rs) repo) and be Verifiable Data Registry-agnostic. 66 | - The Hyperledger Aries Issue Credential ([v1](https://github.com/hyperledger/aries-rfcs/blob/main/features/0036-issue-credential/README.md), [v2](https://github.com/hyperledger/aries-rfcs/blob/master/features/0453-issue-credential-v2/README.md)) and Present Proof ([v1](https://github.com/hyperledger/aries-rfcs/blob/master/features/0037-present-proof/README.md), [v2](https://github.com/hyperledger/aries-rfcs/blob/main/features/0454-present-proof-v2/README.md)) protocols defined in the [Aries RFC](https://github.com/hyperledger/aries-rfcs) repository of standards and protocols. 67 | 68 | ## Meeting Schedule and Notes 69 | 70 | Meetings of the Working Group are held weekly on Mondays at 7AM Pacific/Vancouver time. That is 16:00 CET for most of the year, except for the periods around the daylight savings time changes. Meeting details, agendas, notes and links to the recordings are posted [here](https://wiki.hyperledger.org/display/ANONCREDS/Meetings%3A+AnonCreds+Specification+Working+Group). 71 | 72 | ## Mailing List and Communications 73 | 74 | This task force uses the following for communications 75 | 76 | - Mailing List: Information about the mailing list for Hyperledger AnonCreds is available here: https://lists.hyperledger.org/g/anoncreds, including guidance on subscribing to the list and access to the mailing list archives. 77 | - Messaging: Hyperledger Discord invitation: [https://discord.gg/hyperledger](https://discord.gg/hyperledger) 78 | - Hyperledger AnonCreds Wiki Home Page: The Working group uses the Hyperledger Wiki at: [https://wiki.hyperledger.org/display/anoncreds](https://wiki.hyperledger.org/display/anoncreds) 79 | 80 | ## About This Document 81 | 82 | Include in this document a detailed description of this Working Group’s Scope. 83 | This Scope is important is it establishes the bounds of each contributor's and 84 | licensee's patent commitment. For guidance on drafting an appropriate Scope, you 85 | may find [ISO's guidance (see page 5)](https://www.iso.org/files/live/sites/isoorg/files/developing_standards/docs/en/how-to-write-standards.pdf "ISO How To Write Standards Guide") helpful. 86 | 87 | Any changes of Scope are not retroactive. 88 | -------------------------------------------------------------------------------- /3._Notices.md: -------------------------------------------------------------------------------- 1 | # Notices 2 | 3 | ## Code of Conduct 4 | 5 | Contact for [Code of Conduct](8._Code_of_Conduct.md) issues or inquires: Stephen Curran [swcurran@cloudcompass.ca](mailto:swcurran@cloudcompass.ca). 6 | 7 | ## License Acceptance 8 | 9 | Per [Community Specification License 1.0 Section 2.1.3.3](https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md), Licensees may indicate their acceptance of the Community Specification License by issuing a pull request to the Specification’s repository’s 3_Notices.md file (this file), including the Licensee’s name, authorized individuals' names, and repository system identifier (e.g. GitHub ID), and specification version. 10 | 11 | A Licensee may consent to accepting the current Community Specification License version or any future version of the Community Specification License by indicating "or later" after their specification version. 12 | 13 | - Licensee’s name: 14 | - Authorized individual and system identifier: 15 | - Specification version: 16 | 17 | ## Withdrawals 18 | 19 | - Name of party withdrawing: 20 | - Date of withdrawal: 21 | 22 | ## Exclusions 23 | 24 | This section includes any Exclusion Notices made against a Draft Deliverable or Approved Deliverable as set forth in the Community Specification Development License. 25 | 26 | *Insert exclusions here* 27 | 28 | ### Required Exclusion Information 29 | 30 | Each Exclusion Notice must include the following information: 31 | 32 | - Name of party making the Exclusion Notice: 33 | - Name of patent owner: 34 | - Specification: 35 | - Version number: 36 | 37 | **For issued patents and published patent applications:** 38 | 39 | (i) patent number(s) or title and application number(s), as the case may be: 40 | 41 | (ii) identification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim. 42 | 43 | **For unpublished patent applications must provide either:** 44 | 45 | (i) the text of the filed application; or 46 | 47 | (ii) identification of the specific part(s) of the Specification whose implementation makes the excluded claim a Necessary Claim. 48 | -------------------------------------------------------------------------------- /4._License.md: -------------------------------------------------------------------------------- 1 | # Licenses 2 | 3 | ## Specification License 4 | 5 | Specifications in the repository are subject to the **Community Specification License 1.0** available at [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0). 6 | 7 | ## Source Code License 8 | 9 | If source code is included in this repository, or for sample or reference code included in the specification itself, that code is subject to the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) unless otherwise designated. In the case of any conflict or confusion within this specification repository between the [Community Specification License](https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md) and the [Apache 2.0 license](https://www.apache.org/licenses/LICENSE-2.0.txt) or other designated license, the terms of the [Community Specification License](https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md) shall apply. 10 | 11 | If source code is included in this repository, or for sample or reference code included in the specification itself, that code is subject to the Apache 2.0 license unless otherwise marked. In the case of any conflict or confusion within this specification repository between the Community Specification License and the designated source code license, the terms of the Community Specification License shall apply. 12 | -------------------------------------------------------------------------------- /5._Governance.md: -------------------------------------------------------------------------------- 1 | # Community Specification Governance Policy 1.0 2 | 3 | This document provides the governance policy for specifications and other documents developed using the Community Specification process in a repository (each a “Working Group”). Each Working Group and must adhere to the requirements in this document. 4 | 5 | ## 1. Roles 6 | 7 | Each Working Group may include the following roles. Additional roles may be adopted and documented by the Working Group. 8 | 9 | **1.1. Maintainer.** “Maintainers” are responsible for organizing activities around developing, maintaining, and updating the specification(s) developed by the Working Group. Maintainers are also responsible for determining consensus and coordinating appeals. Each Working Group will designate one or more Maintainer for that Working Group. A Working Group may select a new or additional Maintainer(s) upon Approval of the Working Group Participants. 10 | 11 | **1.2. Editor.** “Editors” are responsible for ensuring that the contents of the document accurately reflect the decisions that have been made by the group, and that the specification adheres to formatting and content guidelines. Each Working Group will designate an Editor for that Working Group. A Working Group may select a new Editor upon Approval of the Working Group Participants. 12 | 13 | **1.3. Participants.** “Participants” are those that have made Contributions to the Working Group subject to the Community Specification License. 14 | 15 | ## 2. Decision Making 16 | 17 | **2.1. Consensus-Based Decision Making.** Working Groups make decisions through a consensus process (“Approval” or “Approved”). While the agreement of all Participants is preferred, it is not required for consensus. Rather, the Maintainer(s) will determine consensus based on their good faith consideration of a number of factors, including the dominant view of the Working Group Participants and nature of support and objections. The Maintainer will document evidence of consensus in accordance with these requirements. 18 | 19 | **2.2. Appeal Process.** Decisions may be appealed be via a pull request or an issue, and that appeal will be considered by the Maintainer(s) in good faith, who will respond in writing within a reasonable time. 20 | 21 | ## 3. Ways of Working 22 | 23 | Inspired by [ANSI’s Essential Requirements for Due Process](https://share.ansi.org/Shared%20Documents/Standards%20Activities/American%20National%20Standards/Procedures,%20Guides,%20and%20Forms/2020_ANSI_Essential_Requirements.pdf), Community Specification Working Groups must adhere to consensus-based due process requirements. These requirements apply to activities related to the development of consensus for approval, revision, reaffirmation, and withdrawal of Community Specifications. Due process means that any person (organization, company, government agency, individual, etc.) with a direct and material interest has a right to participate by: a) expressing a position and its basis, b) having that position considered, and c) having the right to appeal. Due process allows for equity and fair play. The following constitute the minimum acceptable due process requirements for the development of consensus. 24 | 25 | **3.1. Openness.** Participation shall be open to all persons who are directly and materially affected by the activity in question. There shall be no undue financial barriers to participation. Voting membership on the consensus body shall not be conditional upon membership in any organization, nor unreasonably restricted on the basis of technical qualifications or other such requirements. Membership in a Working Group’s parent organization, if any, may be required. 26 | 27 | **3.2. Lack of Dominance.** The development process shall not be dominated by any single interest category, individual or organization. Dominance means a position or exercise of dominant authority, leadership, or influence by reason of superior leverage, strength, or representation to the exclusion of fair and equitable consideration of other viewpoints. 28 | 29 | **3.3. Balance.** The development process should have a balance of interests. Participants from diverse interest categories shall be sought with the objective of achieving balance. 30 | 31 | **3.4. Coordination and Harmonization.** Good faith efforts shall be made to resolve potential conflicts between and among deliverables developed under this Working Group and existing industry standards. 32 | 33 | **3.5. Consideration of Views and Objections.** Prompt consideration shall be given to the written views and objections of all Participants. 34 | 35 | **3.6. Written procedures.** This governance document and other materials documenting the Community Specification development process shall be available to any interested person. 36 | 37 | ## 4. Specification Development Process 38 | 39 | **4.1. Pre-Draft.** Any Participant may submit a proposed initial draft document as a candidate Draft Specification of that Working Group. The Maintainer will designate each submission as a “Pre-Draft” document. 40 | 41 | **4.2. Draft.** Each Pre-Draft document of a Working Group must first be Approved to become a” Draft Specification”. Once the Working Group approves a document as a Draft Specification, the Draft Specification becomes the basis for all going forward work on that specification. 42 | 43 | **4.3. Working Group Approval.** Once a Working Group believes it has achieved the objectives for its specification as described in the Scope, it will Approve that Draft Specification and progress it to “Approved Specification” status. 44 | 45 | **4.4. Publication and Submission.** Upon the designation of a Draft Specification as an Approved Specification, the Maintainer(s) will publish the Approved Specification in a manner agreed upon by the Working Group Participants (i.e., Working Group Participant only location, publicly available location, Working Group maintained website, Working Group member website, etc.). The publication of an Approved Specification in a publicly accessible manner must include the terms under which the Approved Specification is being made available under. 46 | 47 | **4.5. Submissions to Standards Bodies.** No Draft Specification or Approved Specification may be submitted to another standards development organization without Working group Approval. Upon reaching Approval, the Maintainer will coordinate the submission of the applicable Draft Specification or Approved Specification to another standards development organization. Working Group Participants that developed that Draft Specification or Approved Specification agree to grant the copyright rights necessary to make those submissions. 48 | 49 | ## 5. Non-Confidential, Restricted Disclosure 50 | 51 | Information disclosed in connection with any Working Group activity, including but not limited to meetings, Contributions, and submissions, is not confidential, regardless of any markings or statements to the contrary. Notwithstanding the foregoing, if the Working Group is collaborating via a private repository, the Participants will not make any public disclosures of that information contained in that private repository without the Approval of the Working Group. 52 | -------------------------------------------------------------------------------- /6._Contributing.md: -------------------------------------------------------------------------------- 1 | # Community Specification Contribution Policy 1.0 2 | 3 | This document provides the contribution policy for specifications and other documents developed using the Community Specification process in a repository (each a “Working Group”). Additional or alternate contribution policies may be adopted and documented by the Working Group. 4 | 5 | ## 1. Contribution Guidelines 6 | 7 | This Working Group accepts contributions via pull requests. The following section outlines the process for merging contributions to the specification 8 | 9 | ### 1.1. Issues 10 | 11 | Issues are used as the primary method for tracking anything to do with this specification Working Group. 12 | 13 | #### 1.1.1 Issue Types 14 | 15 | There are three types of issues (each with their own corresponding label): 16 | 17 | ##### 1.1.1.1 Discussions 18 | 19 | These are support or functionality inquiries that we want to have a record of for future reference. Depending on the discussion, these can turn into "Spec Change" issues. 20 | 21 | ##### 1.1.1.2 Proposals 22 | 23 | Used for items that propose a new ideas or functionality that require a larger discussion. This allows for feedback from others before a specification change is actually written. All issues that are proposals should both have a label and an issue title of "Proposal: [the rest of the title]." A proposal can become a "Spec Change" and does not require a milestone. 24 | 25 | ##### 1.1.1.3 Spec Changes 26 | 27 | These track specific spec changes and ideas until they are complete. They can evolve from "Proposal" and "Discussion" items, or can be submitted individually depending on the size. Each spec change should be placed into a milestone. 28 | 29 | ## 2. Issue Lifecycle 30 | 31 | The issue lifecycle is mainly driven by the Maintainer(s). All issue types follow the same general lifecycle. Differences are noted below. 32 | 33 | ### 2.1. Issue Creation 34 | 35 | An issue is created. 36 | 37 | ### 2.2. Triage 38 | 39 | - The Editor in charge of triaging will apply the proper labels for the issue. This includes labels for priority, type, and metadata. 40 | - (If needed) Clean up the title to succinctly and clearly state the issue. Also ensure that proposals are prefaced with "Proposal". 41 | 42 | ### 2.3. Discussion 43 | 44 | - "Spec Change" issues should be connected to the pull request that resolves it. 45 | - Whoever is working on a "Spec Change" issue should either assign the issue to themselves or make a comment in the issue saying that they are taking it. 46 | - "Proposal" and "Discussion" issues should stay open until resolved. 47 | 48 | ### 2.4. Issue Closure 49 | 50 | When the Working Group reaches consensus on the issue, via either a pull request to the specification that is merged or a decision that the issue does not change the specification, the issue is closed. 51 | 52 | ## 3. How to Contribute a Patch 53 | 54 | The Working Group uses pull requests to track changes. To submit a change to the specification: 55 | 56 | ### 3.1 Create the Pull Request 57 | 58 | Fork the Repo, modify the specification to address the issue in your fork. 59 | 60 | ### 3.2. Submit a Pull Request 61 | 62 | Submit the local change as a pull request to the specification's repo. 63 | 64 | ## 4. Pull Request Workflow 65 | 66 | The next section contains more information on the workflow followed for Pull Requests. 67 | 68 | ### 4.1. Pull Request Creation 69 | 70 | - We welcome pull requests that are currently in progress. They are a great way to keep track of important work that is in-flight, but useful for others to see. If a pull request is a work in progress, the pull request title should be prefaced with "WIP: ", and the "wip" label applied. Once the pull request is ready for review, remove "WIP" from the title and remove the "wip" label. 71 | - It is preferred, but not required, to have a pull request tied to a specific issue. There can be circumstances where if it is a quick fix then an issue might be overkill. The details provided in the pull request description would suffice in this case. 72 | 73 | ### 4.2. Triage 74 | 75 | - The Editor in charge of triaging will apply the proper labels for the pull request. This should include at least labels for size, a delivery milestone, and awaiting review. 76 | 77 | ### 4.3. Reviewing/Discussion 78 | 79 | - All reviews will be completed using the review tool. 80 | - A "Comment" review should be used when there are questions about the spec that should be answered, but that don't involve spec changes. This type of review does not count as approval. 81 | - A "Changes Requested" review indicates that changes to the spec need to be made before they will be merged. 82 | - Reviewers should update labels as needed (such as needs rebase). 83 | - When a review is approved, the reviewer should add at least "LGTM" as a comment. 84 | - Final approval is required by a designated Editor. Merging is blocked without this final approval. Editors will factor reviews from all other reviewers into their approval process. 85 | 86 | ### 4.4. Responsive 87 | 88 | A pull request owner should try to be responsive to comments by answering questions or changing text. Once all comments have been addressed, an Editor-approved pull request is ready to be merged 89 | 90 | ### 4.5. Merge or Close 91 | 92 | - A pull request should stay open until a Maintainer has marked the pull request as approved. 93 | - Pull requests can be closed by the author without merging. 94 | - Pull requests may be closed by a Maintainer if the decision is made that it is not going to be merged. 95 | -------------------------------------------------------------------------------- /8._Code_of_Conduct.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Code of Conduct 2 | 3 | The AnonCreds Specification Working Group uses the [Hyperledger Code of Conduct](https://wiki.hyperledger.org/display/HYP/Hyperledger+Code+of+Conduct). All Working Group contributors and meeting attendees are asked 4 | to review and follow the code of conduct. 5 | 6 | ![Hyperledger Code of Conduct, Everyone is Welcome](https://wiki.hyperledger.org/download/attachments/2392771/welcome.png?version=2&modificationDate=1572450107000&api=v2) -------------------------------------------------------------------------------- /EditingTheSpec.md: -------------------------------------------------------------------------------- 1 | # Editing the Specification 2 | 3 | To contribute changes to the specification, please 4 | 5 | - Review the [Contributions policy](6._Contributing.md) for this specification and ensure that you and your organization are willing to abide by the policy. 6 | - **Pull requests submitted to this repository imply acceptance of the [Contributions policy](6._Contributing.md).** 7 | - Submit a pull request by: 8 | - forking this repo 9 | - editing the appropriate markdown files in the [`/spec`](/spec) folder 10 | 11 | The specification source consists of the markdown files listed in 12 | [specs.json](/specs.json) and found in the [`/spec`](/spec) folder. The 13 | specification is automatically rendered (using 14 | [Spec-Up](https://github.com/decentralized-identity/spec-up)) to the `/docs` 15 | folder of the `gh-pages` branch of this repository on each pull request merge 16 | (using a GitHub Action), and then published (using GitHub Pages). 17 | 18 | ## Testing your Edits Locally 19 | 20 | Full guidance for using Spec-Up is in its 21 | [repository](https://github.com/decentralized-identity/spec-up). The short 22 | version of the instructions to render this specification locally while you are 23 | editing is: 24 | 25 | - Install the prerequisites: `node` and `npm` 26 | - Run `npm install` from the root of the repository 27 | - Run `npm run edit` from the root of the repository to render the document with 28 | live updates to the `docs/index.html` as 29 | you edit the source files. 30 | - You can also run `npm run render` to just generate the specification file once. 31 | - Open the rendered file in a browser and refresh to see your updates as you work. 32 | - When you are done, hit `Ctrl-c` to exit the live rendering. 33 | 34 | Please check your edits locally before you submit a pull request! 35 | 36 | ### Handling the Rendered Specification File 37 | 38 | When you create a pull request to update the specification, the `docs/index.html` will be 39 | .gitignore'd and **not** included in your pull request. A GitHub Action triggered on merging pull requests automagically renders the full 40 | specification (`docs/index.html`) to the `gh-pages` branch in the repository and the 41 | specification is published (via GitHub Pages) from there. 42 | 43 | ## Adding a New Source Markdown File 44 | 45 | If you add a source markdown file to the specification, you must also add a reference 46 | to it in the [specs.json](/specs.json) in the root of the repository. 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | ## Active Maintainers 4 | 5 | 6 | 7 | | Name | Github | LFID | 8 | | ---------------- | ---------------- | ---------------- | 9 | | Artur Philipp | ArPhil | | 10 | | Hakan Yildiz | hkny | | 11 | | Stephen Curran | swcurran | | 12 | | Sam Curren | TelegramSam | | 13 | | Víctor Martínez Jurado | victormartinez-work | | 14 | 15 | ## Emeritus Maintainers 16 | 17 | | Name | Github | LFID | 18 | |--------------|---------|---------| 19 | | | | | 20 | 21 | ## Becoming a Maintainer 22 | 23 | The AnonCred Specification Working Group within the Hyperledger AnonCreds 24 | community welcomes contributions. All contributors to the AnonCreds 25 | specification agree to the [Community License Specification 26 | v1.0](/1._Community_Specification_License-v1.md) under which the Working Group 27 | operates. 28 | 29 | Contributors may progress to become a maintainer. To become a 30 | maintainer the following steps occur, roughly in order. 31 | 32 | - 5 significant changes have been authored by the proposed maintainer and 33 | accepted. 34 | - The proposed maintainer has the sponsorship of at least one other maintainer. 35 | - This sponsoring maintainer will create a PR modifying the list of 36 | maintainers. 37 | - The proposed maintainer accepts the nomination and expresses a willingness 38 | to be a long-term (more than 6 month) maintainer. 39 | - This would be a comment in the above PR. 40 | - This PR will be communicated in all appropriate communication channels. It 41 | should be mentioned in any maintainer/community call. It should also be 42 | posted to the appropriate mailing list or chat channels if they exist. 43 | - Approval by at least 3 current maintainers within two weeks of the proposal or 44 | an absolute majority of current maintainers. 45 | - These votes will be recorded in the PR modifying the list of maintainers. 46 | - No veto by another maintainer within two weeks of proposal are recorded. 47 | - All vetoes must be accompanied by a public explanation as a comment in the 48 | PR for adding this maintainer 49 | - The explanation of the veto must be reasonable. 50 | - A veto can be retracted, in that case the approval/veto timeframe is reset. 51 | - It is bad form to veto, retract, and veto again. 52 | - The proposed maintainer becomes a maintainer 53 | - Either two weeks have passed since the third approval, 54 | - Or an absolute majority of maintainers approve. 55 | - In either case, no maintainer presents a veto. 56 | 57 | ## Removing Maintainers 58 | 59 | Being a maintainer is not a status symbol or a title to be maintained 60 | indefinitely. It will occasionally be necessary and appropriate to move a 61 | maintainer to emeritus status. This can occur in the following situations: 62 | 63 | - Resignation of a maintainer. 64 | - Violation of the [Hyperledger Code of 65 | Conduct](https://wiki.hyperledger.org/display/HYP/Hyperledger+Code+of+Conduct) 66 | warranting removal. 67 | - Inactivity. 68 | - A general measure of inactivity will be no commits or code review comments 69 | for one reporting quarter, although this will not be strictly enforced if 70 | the maintainer expresses a reasonable intent to continue contributing. 71 | - Reasonable exceptions to inactivity will be granted for known long term 72 | leave such as parental leave and medical leave. 73 | - Other unspecified circumstances. 74 | 75 | Like adding a maintainer the record and governance process for moving a 76 | maintainer to emeritus status is recorded in the github PR making that change. 77 | 78 | Returning to active status from emeritus status uses the same steps as adding a 79 | new maintainer. Note that the emeritus maintainer already has the 5 required 80 | significant changes as there is no contribution time horizon for those. 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AnonCreds Specification 2 | 3 | ![AnonCreds Logo](/spec/images/logo/hl_anoncreds_colour.svg) 4 | 5 | This repository contains the source content for the AnonCreds open 6 | specification, a part of the [Hyperledger AnonCreds 7 | Project](https://wiki.hyperledger.org/display/anoncreds). This open 8 | specification is based on the open source AnonCreds verifiable credential 9 | implementation in the Hyperledger AnonCreds GitHub repository 10 | [anoncreds-rs](https://github.com/hyperledger/anoncreds-rs). That implementation 11 | was originally part of the [Hyperledger 12 | Indy](https://www.hyperledger.org/projects/hyperledger-indy) open source 13 | project, accepted into Hyperledger in 2017. The extensive use of AnonCreds 14 | around the world has made it a de facto standard, and the AnonCreds Working 15 | Group (hyperledger) has been established to formalize the specification and 16 | place it on a standards track. 17 | 18 | - This work is being conducted under the [Community Specification License v1.0](1._Community_Specification_License-v1.md) 19 | - The draft specification can be found here: [https://hyperledger.github.io/anoncreds-spec/](https://hyperledger.github.io/anoncreds-spec/) 20 | - The source specification documents can be found here: [Specification Source](/spec) 21 | 22 | This repository contains guidelines for [contributing](#contributions) to the specification and submitting [edits via GitHub pull requests](/EditingTheSpec.md). 23 | 24 | ## Background 25 | 26 | The scope and background for this work can be found in the [Scope](2._Scope.md) in 27 | this repository. The summary is the following: 28 | 29 | The open source AnonCreds implementations 30 | ([here](https://github.com/hyperledger/indy-sdk/blob/master/libindy/src/api/anoncreds.rs) 31 | in [Hyperledger 32 | Indy](https://www.hyperledger.org/projects/hyperledger-indy) and [here](https://github.com/hyperledger/anoncreds-rs)) in [Hyperledger AnonCreds](https://wiki.hyperledger.org/display/anoncreds) 33 | provide 34 | capabilities that many see as important for digital identity use cases in 35 | particular, and verifiable data in general. These features include: 36 | 37 | - A full implementation of the Layer 3 verifiable credential “Trust Triangle” of the [Trust over IP Model](https://trustoverip.org/wp-content/toip-model/). 38 | - Complete flows for issuing verifiable credentials (Issuer to Holder), and requesting, generating and verifying presentations of verifiable claims (Holder to Verifier). 39 | - Fully defined data models for all of the objects in the flows, including verifiable credentials, presentation requests and presentations sourced from multiple credentials. 40 | - Fully defined applications of cryptographic primitives. 41 | - 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: 42 | - Blinding issuer signatures to prevent correlation based on those signatures. 43 | - Holder binding based on the use of unrevealed identifiers to prevent correlation based a holder identifier. 44 | - Selective disclosure in the generation of presentations to minimize data sharing to that required for the business need. 45 | - The use of predicate proofs to reduce the sharing of PII and potentially correlating data, especially dates (birth, credential issuance/expiry, etc.). 46 | - A revocation scheme that proves a presentation is based on credentials that have not been revoked by the issuers without revealing correlatable revocation identifiers. 47 | 48 | The AnonCreds working group is producing an AnonCreds v1.0 specification that 49 | describes the existing implementation minus any dependency on the Hyperledger 50 | Indy ledger ("ledger-agnostic"). Once sufficient progress has been made on the v1.0 specification, a 51 | forward looking version will be started that evolves the specification to add 52 | new elements while retaining the core features of AnonCreds (listed above). Such 53 | a future version is likely to include features such as replacing CL Signatures 54 | with BBS+ Signatures, defining a more scalable revocation scheme. Those participating in this Working Group will define the exact direction 55 | of future versions of the AnonCreds specification. 56 | 57 | ## Contributions 58 | 59 | This work is being carried out under the [Community Specification License 60 | v1.0](1._Community_Specification_License-v1.md). Any person or organization 61 | willing to adhere to this license is welcome to participate in this Working 62 | Group and contribute to the development of the specification. Please read the 63 | [Contributions](6._Contributing.md) document in this repo for details. For those 64 | unfamiliar with the Community Specification License, you can think of it as 65 | analogous to an open source code license, such as Apache 2.0, but for 66 | specifications. 67 | 68 | All participants in this working group must follow the group's [Code of Conduct](8._Code_of_Conduct.md). 69 | 70 | ## Meetings 71 | 72 | Meetings of the Working Group are held weekly on Mondays at 7AM 73 | Pacific/Vancouver time. That is 16:00 CET for most of the year, except for the 74 | periods around the daylight savings time changes. Meeting details, agendas, 75 | notes and links to the recordings are posted on the repository Wiki (to be done). 76 | 77 | ## Working Group Communications 78 | 79 | The working group has an [AnonCreds Specification](https://discord.com/channels/905194001349627914/1037471404586709042) Discord channel for participants. Invitations for those interested: [https://discord.gg/hyperledger](https://discord.gg/hyperledger). 80 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Hyperledger AnonCreds Security Policy 2 | 3 | ## About this document 4 | 5 | This document defines how security vulnerability reporting is handled in the 6 | Hyperledger AnonCreds project. The approach aligns with the [Hyperledger 7 | Foundation's Security Vulnerability Reporting 8 | policy](https://toc.hyperledger.org/governing-documents/security.html). Please 9 | review that document to understand the basis of the security reporting for 10 | Hyperledger AnonCreds. 11 | 12 | The Hyperledger Security Vulnerability policy borrows heavily from the 13 | recommendations of the OpenSSF Vulnerability Disclosure working group. For 14 | up-to-date information on the latest recommendations related to vulnerability 15 | disclosures, please visit the [GitHub of that working 16 | group](https://github.com/ossf/wg-vulnerability-disclosures). 17 | 18 | If you are already familiar with the security policies of Hyperledger AnonCreds, and 19 | ready to report a vulnerability, please jump to [Report 20 | Intakes](#report-intakes). 21 | 22 | ## Outline 23 | 24 | This document has the following sections: 25 | 26 | - [Hyperledger AnonCreds Security Policy](#hyperledger-project-security-policy) 27 | - [Instructions](#instructions) 28 | - [About this document](#about-this-document) 29 | - [Outline](#outline) 30 | - [What Is a Vulnerability Disclosure Policy?](#what-is-a-vulnerability-disclosure-policy) 31 | - [Security Team](#security-team) 32 | - [Discussion Forums](#discussion-forums) 33 | - [Report Intakes](#report-intakes) 34 | - [CNA/CVE Reporting](#cnacve-reporting) 35 | - [Embargo List](#embargo-list) 36 | - [(GitHub) Security Advisories](#github-security-advisories) 37 | - [Private Patch Deployment Infrastructure](#private-patch-deployment-infrastructure) 38 | 39 | ## What Is a Vulnerability Disclosure Policy? 40 | 41 | No piece of software is perfect. All software (at least, all software of a 42 | certain size and complexity) has bugs. In open source development, members of 43 | the community or the public find bugs and report them to the project. A 44 | vulnerability disclosure policy explains how this process functions from the 45 | perspective of the project. 46 | 47 | This vulnerability disclosure policy explains the rules and guidelines for 48 | Hyperledger AnonCreds. It is intended to act as both a reference for 49 | outsiders–including both bug reporters and those looking for information on the 50 | project’s security practices–as well as a set of rules that maintainers and 51 | contributors have agreed to follow. 52 | 53 | ## Security Team 54 | 55 | The current Hyperledger AnonCreds security team is: 56 | 57 | | Name | Email ID | Discord ID | Area/Specialty | 58 | | --------------- | ------------------------------- | ---------- | ---------------------- | 59 | | Stephen Curran | swcurran@cloudcompass.ca | | AnonCreds Applications | 60 | | Mike Lodder | redmike7@gmail.com | | Cryptography | 61 | | Hart Montgomery | hmontgomery@linuxfoundation.org | <> | Cryptograhy | 62 | | Sam Curren | sam@indicio.tech | <> | AnonCreds Applications | 63 | 64 | The security team for Hyperledger AnonCreds must include at least three project 65 | Maintainers that agree to carry out the following duties and responsibilities. 66 | Members are added and removed from the team via approved Pull Requests to this 67 | repository. For additional background into the role of the security team, see 68 | the [People Infrastructure] section of the Hyperledger Security Policy. 69 | 70 | [People Infrastructure]: https://toc.hyperledger.org/governing-documents/security.html#people-infrastructure 71 | 72 | **Responsibilities:** 73 | 74 | 1. Acknowledge the receipt of vulnerability reports to the reporter within 2 75 | business days. 76 | 77 | 2. Assess the issue. Engage with the reporter to ask any outstanding questions 78 | about the report and how to reproduce it. If the report was received by email 79 | and may be a security vulnerability, open a GitHub Security Advisory on the 80 | repository to manage the report. If the report is not considered a 81 | vulnerability, then the reporter should be informed and this process can be 82 | halted. If the report is a regular bug (but not a security vulnerability), the 83 | reporter should be informed (if necessary) of the regular process for reporting 84 | issues. 85 | 86 | 3. Some issues may require more time and resources to correct. If a particular 87 | report is complex, discuss an embargo period with the reporter during which 88 | time the report will not be publicly disclosed. The embargo period should be 89 | negotiated with the reporter and must not be longer than 90 days. 90 | 91 | 4. If necessary, create a private patch development infrastructure for the issue 92 | by emailing the [Hyperledger Community Architects]. 93 | 94 | [Hyperledger Community Architects]: mailto:community-architects@hyperledger.org 95 | 96 | 5. Request a CVE for the issue (see the [CNA/CVE Reporting](#cnacve-reporting) 97 | section). 98 | 99 | 6. Decide a date for the public release of the vulnerability report, the date 100 | the embargo period ends. 101 | 102 | 7. If applicable, notify members of the embargo list of the vulnerability, 103 | upcoming patch and release, as described above. 104 | 105 | 8. Publish a new (software) release in which the vulnerability is addressed. 106 | 107 | 9. Publicly disclose the issue within 48 hours after the release via a 108 | GitHub security advisory (see the [(GitHub) Security 109 | Advisories](#github-security-advisories) section for details). 110 | 111 | ## Discussion Forums 112 | 113 | Discussions about each reported vulnerability should be carried out in the 114 | private GitHub security advisory about the vulnerability. If necessary, a private 115 | channel specific to the issue may be created on the Hyperledger Discord server 116 | with invited participants added to the discussion. 117 | 118 | ## Report Intakes 119 | 120 | Hyperledger AnonCreds has the following ways to submit security 121 | vulnerabilities. While the security team members will do their best to 122 | respond to bugs disclosed in all possible ways, it is encouraged for bug 123 | finders to report through the following approved channels: 124 | 125 | - Email the [Hyperledger Foundation security 126 | list](mailto:security@lists.hyperledger.org): To report a security issue, please 127 | send an email with the name of the project/repository, a description of the issue, the 128 | steps you took to create the issue, affected versions, and if known, 129 | mitigations. If in triaging the email, the security team determines the issue may be 130 | a security vulnerability, a [GitHub security vulnerability report] will be 131 | opened. 132 | - Open a [GitHub security vulnerability report]: Open a draft security advisory 133 | on the "Security" tab of this GitHub repository. See [GitHub Security 134 | Advisories](#github-security-advisories) to learn more about the security 135 | infrastructure in GitHub. 136 | 137 | [GitHub security vulnerability report]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability 138 | 139 | ## CNA/CVE Reporting 140 | 141 | Hyperledger AnonCreds maintains a list of **Common Vulnerabilities and Exposures 142 | (CVE)** and uses GitHub as its **CVE numbering authority (CNA)** for issuing 143 | CVEs. 144 | 145 | ## Embargo List 146 | 147 | Hyperledger AnonCreds maintains a private embargo list. If you wish to 148 | be added to the embargo list, please email the [Hyperledger Foundation security 149 | mailing list](mailto:security@lists.hyperledger.org), including the project name 150 | (Hyperledger AnonCreds) and reason for being added to the embargo list. Requests 151 | will be assessed by the Hyperledger AnonCreds security team in conjunction with the 152 | appropriate Hyperledger Staff, and a decision will be made to accommodate or not 153 | the request. 154 | 155 | For more information about the embargo list, please see the [Embargo List 156 | section of the Hyperledger Security 157 | Policy](https://toc.hyperledger.org/governing-documents/security.html#embargo-list). 158 | 159 | ## (GitHub) Security Advisories 160 | 161 | Hyperledger AnonCreds uses GitHub Security Advisories to manage the public 162 | disclosure of security vulnerabilities. 163 | 164 | ## Private Patch Deployment Infrastructure 165 | 166 | In creating patches and new releases that address security vulnerabilities, 167 | Hyperledger AnonCreds uses the private development features of GitHub for security 168 | vulnerabilities. GitHub has [extensive 169 | documentation](https://docs.github.com/en/code-security/security-advisories/repository-security-advisories) 170 | about these features. 171 | -------------------------------------------------------------------------------- /assets/compiled/head.js: -------------------------------------------------------------------------------- 1 | function delegateEvent(e,t,n,a={}){return(a.container||document).addEventListener(e,e=>{let a=e.target.closest(t);a&&n(e,a)},a)}skipAnimationFrame=e=>requestAnimationFrame(()=>requestAnimationFrame(e));var domReady=new Promise(e=>{document.addEventListener("DOMContentLoaded",t=>e())}); 2 | customElements.define("slide-panels",class extends HTMLElement{static get observedAttributes(){return["open"]}constructor(){super(),this.addEventListener("pointerup",e=>{e.target===this&&this.close()})}get active(){return this.getAttribute("open")}toggle(e){this.active===e?this.close():this.open(e)}open(e){this.setAttribute("open",e)}close(){this.removeAttribute("open")}attributeChangedCallback(e,t,s){switch(e){case"open":for(let e of this.children)e.id===s?e.setAttribute("open",""):e.removeAttribute("open","")}}}),customElements.define("detail-box",class extends HTMLElement{static get observedAttributes(){return["open"]}constructor(){super(),this.addEventListener("pointerup",e=>{e.target.hasAttribute("detail-box-toggle")&&(e.stopPropagation(),this.toggle())}),this.addEventListener("transitionend",e=>{let t=e.target;t.parentElement===this&&"SECTION"===t.tagName&&"height"===e.propertyName&&(t.style.height=this.hasAttribute("open")?"auto":null)})}toggle(){this.toggleAttribute("open")}attributeChangedCallback(e,t,s){switch(e){case"open":for(let e of this.children)if("SECTION"===e.tagName){if(null!==s)e.offsetHeight0){e.style.height=e.offsetHeight+"px";this.scrollHeight;e.style.height=0}break}}}}),customElements.define("tab-panels",class extends HTMLElement{constructor(){super(),delegateEvent("click","tab-panels > nav > *",(e,t)=>{let s=t.parentElement;s.parentElement===this&&this.setAttribute("selected-index",Array.prototype.indexOf.call(s.children,t))},{container:this,passive:!0})}static get observedAttributes(){return["selected-index"]}attributeChangedCallback(e,t,s){domReady.then(()=>{switch(e){case"selected-index":let e=s||0,t=this.querySelector("nav");if(t.parentElement===this){let s=t.children,i=s[e];for(let e of s)e.removeAttribute("selected");i&&i.setAttribute("selected","");let r=Array.prototype.filter.call(this.children,e=>{if("SECTION"===e.tagName)return e.removeAttribute("selected"),!0})[e];r&&r.setAttribute("selected","")}}})}}); -------------------------------------------------------------------------------- /assets/css/chart.css: -------------------------------------------------------------------------------- 1 | /* 2 | * DOM element rendering detection 3 | * https://davidwalsh.name/detect-node-insertion 4 | */ 5 | @keyframes chartjs-render-animation { 6 | from { opacity: 0.99; } 7 | to { opacity: 1; } 8 | } 9 | 10 | .chartjs-render-monitor { 11 | animation: chartjs-render-animation 0.001s; 12 | } 13 | 14 | /* 15 | * DOM element resizing detection 16 | * https://github.com/marcj/css-element-queries 17 | */ 18 | .chartjs-size-monitor, 19 | .chartjs-size-monitor-expand, 20 | .chartjs-size-monitor-shrink { 21 | position: absolute; 22 | direction: ltr; 23 | left: 0; 24 | top: 0; 25 | right: 0; 26 | bottom: 0; 27 | overflow: hidden; 28 | pointer-events: none; 29 | visibility: hidden; 30 | z-index: -1; 31 | } 32 | 33 | .chartjs-size-monitor-expand > div { 34 | position: absolute; 35 | width: 1000000px; 36 | height: 1000000px; 37 | left: 0; 38 | top: 0; 39 | } 40 | 41 | .chartjs-size-monitor-shrink > div { 42 | position: absolute; 43 | width: 200%; 44 | height: 200%; 45 | left: 0; 46 | top: 0; 47 | } 48 | -------------------------------------------------------------------------------- /assets/css/custom-elements.css: -------------------------------------------------------------------------------- 1 | 2 | slide-panels { 3 | position: fixed; 4 | top: 0; 5 | left: 0; 6 | height: 100%; 7 | width: 100%; 8 | pointer-events: none; 9 | z-index: 100; 10 | contain: paint; 11 | } 12 | 13 | slide-panels:before { 14 | content: " "; 15 | display: block; 16 | position: fixed; 17 | top: 0; 18 | left: 0; 19 | width: 100%; 20 | height: 100%; 21 | background: rgba(0,0,0,0.3); 22 | transition: opacity 0.35s ease; 23 | opacity: 0; 24 | cursor: pointer; 25 | pointer-events: none; 26 | } 27 | 28 | slide-panels[open]:before { 29 | opacity: 1; 30 | pointer-events: all; 31 | } 32 | 33 | slide-panel { 34 | display: flex; 35 | flex-direction: column; 36 | box-sizing: border-box; 37 | position: absolute; 38 | top: 0; 39 | left: 0; 40 | bottom: 0; 41 | background: #fff; 42 | box-shadow: 0 0 5px 1px rgba(0,0,0,0.15); 43 | transform: translate3d(-100%, 0%, 0); 44 | transition: transform 0.35s ease; 45 | z-index: 1; 46 | pointer-events: all; 47 | } 48 | 49 | slide-panel[options~="right"] { 50 | left: auto; 51 | right: 0; 52 | transform: translate3d(100%, 0%, 0); 53 | } 54 | 55 | slide-panel[open] { 56 | transform: translate3d(0%, 0%, 0); 57 | } 58 | 59 | detail-box { 60 | display: block; 61 | } 62 | 63 | detail-box > header [detail-box-toggle] { 64 | width: 2em; 65 | height: 2em; 66 | text-align: center; 67 | cursor: pointer; 68 | } 69 | 70 | detail-box > header [detail-box-toggle]:before { 71 | content: " "; 72 | display: inline-block; 73 | width: 0; 74 | height: 0; 75 | border-left: 0.55em solid transparent; 76 | border-right: 0.55em solid transparent; 77 | border-top: 0.8em solid; 78 | vertical-align: sub; 79 | cursor: pointer; 80 | } 81 | 82 | detail-box[open] header [detail-box-toggle]:before { 83 | border-top: none; 84 | border-bottom: 0.8em solid; 85 | } 86 | 87 | detail-box > section { 88 | height: 0; 89 | opacity: 0; 90 | min-width: 100%; 91 | transition: height 0.3s ease, opacity 0.3s; 92 | overflow: hidden; 93 | } 94 | 95 | detail-box[open] > section { 96 | opacity: 1; 97 | } 98 | 99 | 100 | /* TAB-PANELS */ 101 | 102 | tab-panels > nav { 103 | display: flex; 104 | } 105 | 106 | tab-panels > nav > * { 107 | margin-left: -2px; 108 | padding: 0.5em 1em; 109 | background: #e0e0e0; 110 | border: 1px solid #aaa; 111 | border-radius: 0; 112 | cursor: pointer; 113 | } 114 | 115 | tab-panels > nav > *:focus { 116 | outline: none; 117 | background: #ccc; 118 | } 119 | 120 | tab-panels > nav > *:first-child { 121 | border-top-left-radius: 5px; 122 | border-bottom-left-radius: 5px; 123 | } 124 | 125 | tab-panels > nav > *:last-child { 126 | border-top-right-radius: 5px; 127 | border-bottom-right-radius: 5px; 128 | } 129 | 130 | tab-panels > nav > *[selected] { 131 | color: var(--themed-element-text); 132 | background: var(--themed-element-bk); 133 | border: var(--themed-element-border); 134 | opacity: 0.9999; 135 | } 136 | 137 | tab-panels > section { 138 | display: none; 139 | } 140 | 141 | tab-panels > section[selected] { 142 | display: block; 143 | } -------------------------------------------------------------------------------- /assets/css/prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.21.0 2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=markup+css+clike+javascript+abnf+diff+git+http+js-extras+json+json5+js-templates+regex&plugins=highlight-keywords */ 3 | /** 4 | * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML 5 | * Based on https://github.com/chriskempson/tomorrow-theme 6 | * @author Rose Pritchard 7 | */ 8 | 9 | code[class*="language-"], 10 | pre[class*="language-"] { 11 | color: #ccc; 12 | background: none; 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | font-size: 1em; 15 | text-align: left; 16 | white-space: pre; 17 | word-spacing: normal; 18 | word-break: normal; 19 | word-wrap: normal; 20 | line-height: 1.5; 21 | 22 | -moz-tab-size: 4; 23 | -o-tab-size: 4; 24 | tab-size: 4; 25 | 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | 31 | } 32 | 33 | /* Code blocks */ 34 | pre[class*="language-"] { 35 | padding: 1em; 36 | margin: .5em 0; 37 | overflow: auto; 38 | } 39 | 40 | :not(pre) > code[class*="language-"], 41 | pre[class*="language-"] { 42 | background: #2d2d2d; 43 | } 44 | 45 | /* Inline code */ 46 | :not(pre) > code[class*="language-"] { 47 | padding: .1em; 48 | border-radius: .3em; 49 | white-space: normal; 50 | } 51 | 52 | .token.comment, 53 | .token.block-comment, 54 | .token.prolog, 55 | .token.doctype, 56 | .token.cdata { 57 | color: #999; 58 | } 59 | 60 | .token.punctuation { 61 | color: #ccc; 62 | } 63 | 64 | .token.tag, 65 | .token.attr-name, 66 | .token.namespace, 67 | .token.deleted { 68 | color: #e2777a; 69 | } 70 | 71 | .token.function-name { 72 | color: #6196cc; 73 | } 74 | 75 | .token.boolean, 76 | .token.number, 77 | .token.function { 78 | color: #f08d49; 79 | } 80 | 81 | .token.property, 82 | .token.class-name, 83 | .token.constant, 84 | .token.symbol { 85 | color: #f8c555; 86 | } 87 | 88 | .token.selector, 89 | .token.important, 90 | .token.atrule, 91 | .token.keyword, 92 | .token.builtin { 93 | color: #cc99cd; 94 | } 95 | 96 | .token.string, 97 | .token.char, 98 | .token.attr-value, 99 | .token.regex, 100 | .token.variable { 101 | color: #7ec699; 102 | } 103 | 104 | .token.operator, 105 | .token.entity, 106 | .token.url { 107 | color: #67cdcc; 108 | } 109 | 110 | .token.important, 111 | .token.bold { 112 | font-weight: bold; 113 | } 114 | .token.italic { 115 | font-style: italic; 116 | } 117 | 118 | .token.entity { 119 | cursor: help; 120 | } 121 | 122 | .token.inserted { 123 | color: green; 124 | } 125 | 126 | -------------------------------------------------------------------------------- /assets/icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /assets/js/custom-elements.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | customElements.define('slide-panels', class SidePanels extends HTMLElement { 5 | static get observedAttributes() { 6 | return ['open']; 7 | } 8 | constructor() { 9 | super(); 10 | 11 | this.addEventListener('pointerup', e => { 12 | if (e.target === this) this.close(); 13 | }) 14 | } 15 | get active (){ 16 | return this.getAttribute('open'); 17 | } 18 | toggle(panel){ 19 | this.active === panel ? this.close() : this.open(panel) 20 | } 21 | open (panel){ 22 | this.setAttribute('open', panel); 23 | } 24 | close (){ 25 | this.removeAttribute('open'); 26 | } 27 | attributeChangedCallback(attr, last, current) { 28 | switch(attr) { 29 | case 'open': for (let child of this.children) { 30 | if (child.id === current) child.setAttribute('open', ''); 31 | else child.removeAttribute('open', ''); 32 | } 33 | break; 34 | } 35 | } 36 | }); 37 | 38 | customElements.define('detail-box', class DetailBox extends HTMLElement { 39 | static get observedAttributes() { 40 | return ['open']; 41 | } 42 | constructor() { 43 | super(); 44 | 45 | this.addEventListener('pointerup', e => { 46 | if (e.target.hasAttribute('detail-box-toggle')) { 47 | e.stopPropagation(); 48 | this.toggle(); 49 | } 50 | }); 51 | 52 | this.addEventListener('transitionend', e => { 53 | let node = e.target; 54 | if (node.parentElement === this && node.tagName === 'SECTION' && e.propertyName === 'height') { 55 | node.style.height = this.hasAttribute('open') ? 'auto' : null; 56 | } 57 | }); 58 | } 59 | toggle(){ 60 | this.toggleAttribute('open'); 61 | } 62 | attributeChangedCallback(attr, last, current) { 63 | switch(attr) { 64 | case 'open': 65 | for (let node of this.children) { 66 | if (node.tagName === 'SECTION') { 67 | if (current !== null) { 68 | if (node.offsetHeight < node.scrollHeight) { 69 | node.style.height = node.scrollHeight + 'px'; 70 | } 71 | } 72 | else if (node.offsetHeight > 0) { 73 | node.style.height = node.offsetHeight + 'px'; 74 | let scroll = this.scrollHeight; 75 | node.style.height = 0; 76 | } 77 | break; 78 | } 79 | } 80 | } 81 | } 82 | }); 83 | 84 | customElements.define('tab-panels', class TabPanels extends HTMLElement { 85 | constructor() { 86 | super(); 87 | delegateEvent('click', 'tab-panels > nav > *', (e, delegate) => { 88 | let nav = delegate.parentElement; 89 | if (nav.parentElement === this) { 90 | this.setAttribute('selected-index', Array.prototype.indexOf.call(nav.children, delegate)) 91 | } 92 | }, { container: this, passive: true }); 93 | } 94 | static get observedAttributes() { 95 | return ['selected-index']; 96 | } 97 | attributeChangedCallback(attr, last, current) { 98 | domReady.then(() => { 99 | switch(attr) { 100 | case 'selected-index': 101 | let index = current || 0; 102 | let nav = this.querySelector('nav'); 103 | if (nav.parentElement === this) { 104 | let tabs = nav.children; 105 | let selected = tabs[index]; 106 | for (let tab of tabs) tab.removeAttribute('selected'); 107 | if (selected) selected.setAttribute('selected', ''); 108 | let panel = Array.prototype.filter.call(this.children, node => { 109 | if (node.tagName === 'SECTION') { 110 | node.removeAttribute('selected'); 111 | return true; 112 | } 113 | })[index]; 114 | if (panel) panel.setAttribute('selected', ''); 115 | } 116 | break; 117 | } 118 | }); 119 | } 120 | }); -------------------------------------------------------------------------------- /assets/js/font-awesome.js: -------------------------------------------------------------------------------- 1 | window.FontAwesomeKitConfig = {"asyncLoading":{"enabled":true},"autoA11y":{"enabled":true},"baseUrl":"https://kit-free.fontawesome.com","detectConflictsUntil":null,"license":"free","method":"css","minify":{"enabled":true},"v4FontFaceShim":{"enabled":true},"v4shim":{"enabled":false},"version":"latest"}; 2 | !function(){function r(e){var t,n=[],i=document,o=i.documentElement.doScroll,r="DOMContentLoaded",a=(o?/^loaded|^c/:/^loaded|^i|^c/).test(i.readyState);a||i.addEventListener(r,t=function(){for(i.removeEventListener(r,t),a=1;t=n.shift();)t()}),a?setTimeout(e,0):n.push(e)}!function(){if(!(void 0===window.Element||"classList"in document.documentElement)){var e,t,n,i=Array.prototype,o=i.push,r=i.splice,a=i.join;d.prototype={add:function(e){this.contains(e)||(o.call(this,e),this.el.className=this.toString())},contains:function(e){return-1!=this.el.className.indexOf(e)},item:function(e){return this[e]||null},remove:function(e){if(this.contains(e)){for(var t=0;t { 9 | slidepanels.toggle(delegate.getAttribute('panel-toggle')); 10 | }, { passive: true }); 11 | 12 | window.addEventListener('hashchange', (e) => slidepanels.close()); 13 | 14 | /* GitHub Issues */ 15 | 16 | let source = specConfig.source; 17 | if (source) { 18 | if (source.host === 'github') { 19 | fetch(`https://api.github.com/repos/${ source.account + '/' + source.repo }/issues`) 20 | .then(response => response.json()) 21 | .then(issues => { 22 | let count = issues.length; 23 | document.querySelectorAll('[issue-count]').forEach(node => { 24 | node.setAttribute('issue-count', count) 25 | }); 26 | repo_issue_list.innerHTML = issues.map(issue => { 27 | return `
  • 28 | 29 |
    ${markdown.render(issue.body)}
    30 |
    31 | ${issue.number} 32 | 33 | ${issue.title} 34 | 35 | 36 |
    37 |
    38 |
  • ` 39 | }).join(''); 40 | Prism.highlightAllUnder(repo_issue_list); 41 | }) 42 | } 43 | } 44 | //${markdown.render(issue.body)} 45 | 46 | /* Mermaid Diagrams */ 47 | 48 | mermaid.initialize({ 49 | startOnLoad: true, 50 | theme: 'neutral' 51 | }); 52 | 53 | /* Charts */ 54 | 55 | document.querySelectorAll('.chartjs').forEach(chart => { 56 | new Chart(chart, JSON.parse(chart.textContent)); 57 | }); 58 | 59 | /* Tooltips */ 60 | let tipMap = new WeakMap(); 61 | delegateEvent('pointerover', '.term-reference, .spec-reference', (e, anchor) => { 62 | let term = document.getElementById((anchor.getAttribute('href') || '').replace('#', '')); 63 | if (!term || tipMap.has(anchor)) return; 64 | let container = term.closest('dt, td:first-child'); 65 | if (!container) return; 66 | let tip = { 67 | allowHTML: true, 68 | inlinePositioning: true 69 | } 70 | switch (container.tagName) { 71 | case 'DT': 72 | tip.content = container.nextElementSibling.textContent; 73 | break; 74 | case 'TD': 75 | let table = container.closest('table'); 76 | let tds = Array.from(container.closest('tr').children); 77 | tds.shift(); 78 | if (table) { 79 | let headings = Array.from(table.querySelectorAll('thead th')); 80 | headings.shift(); 81 | if (headings.length) { 82 | tip.content = ` 83 |
    ${container.textContent}
    84 | 85 | ${headings.map((th, i) => { 86 | return `` 87 | }).join('')} 88 |
    ${th.textContent}:${tds[i] ? tds[i].textContent : ''}
    `; 89 | } 90 | } 91 | break; 92 | } 93 | if (tip.content) tipMap.set(anchor, tippy(anchor, tip)); 94 | }, { passive: true }); 95 | 96 | 97 | })(); 98 | -------------------------------------------------------------------------------- /assets/js/utils.js: -------------------------------------------------------------------------------- 1 | 2 | function delegateEvent(type, selector, fn, options = {}){ 3 | return (options.container || document).addEventListener(type, e => { 4 | let match = e.target.closest(selector); 5 | if (match) fn(e, match); 6 | }, options); 7 | } 8 | 9 | skipAnimationFrame = fn => requestAnimationFrame(() => requestAnimationFrame(fn)); 10 | 11 | var domReady = new Promise(resolve => { 12 | document.addEventListener('DOMContentLoaded', e => resolve()) 13 | }); -------------------------------------------------------------------------------- /custom-assets/custom-body.js: -------------------------------------------------------------------------------- 1 | console.log('Custom javascript in body') -------------------------------------------------------------------------------- /custom-assets/custom-head.js: -------------------------------------------------------------------------------- 1 | console.log('Custom javascript in head') -------------------------------------------------------------------------------- /custom-assets/custom.css: -------------------------------------------------------------------------------- 1 | 2 | body:after { 3 | content: "Custom CSS in body"; 4 | opacity: 0; 5 | pointer-events: none; 6 | } -------------------------------------------------------------------------------- /data/MutiCredentialPresentation.json: -------------------------------------------------------------------------------- 1 | { 2 | "presentation_request": { 3 | "nonce": "182453895158932070575246", 4 | "name": "Step 3 Send your Health Information", 5 | "version": "1.0", 6 | "requested_attributes": { 7 | "biomarker_attrs_0": { 8 | "names": [ 9 | "name", 10 | "concentration", 11 | "unit", 12 | "range", 13 | "collected_on", 14 | "biomarker_id", 15 | "researcher_share" 16 | ], 17 | "restrictions": [ 18 | { 19 | "schema_name": "MYCO Biomarker", 20 | "attr::name::value": "Iron" 21 | } 22 | ] 23 | }, 24 | "consent_attrs": { 25 | "restrictions": [ 26 | { 27 | "schema_name": "MYCO Consent Enablement", 28 | "schema_version": "0.1.0", 29 | "attr::jti_unique_identifier::value": "205b1ea0-7848-48d4-b52b-339122d84f62" 30 | } 31 | ], 32 | "name": "jti_unique_identifier" 33 | } 34 | }, 35 | "requested_predicates": {} 36 | }, 37 | "presentation": { 38 | "proof": { 39 | "proofs": [ 40 | { 41 | "primary_proof": { 42 | "eq_proof": { 43 | "revealed_attrs": { 44 | "biomarker_id": "33034450023603237719386825060766757598085121996569112944281451290292212516012", 45 | "collected_on": "92231735610070911075924224447204218356256133056723930517696107260511721601349", 46 | "concentration": "10", 47 | "name": "85547618788485118809771015708850341281587970912661276233439574555663751388073", 48 | "range": "106828626115908025842177441696860557581575579893927923198365300598359723920768", 49 | "researcher_share": "101264834079306301897660576123112461042861436742738894013248454492965796383403", 50 | "unit": "38351211041892038382023569421847544683371072212679556578649761181279472893849" 51 | }, 52 | "a_prime": "80156520245352052628208149565161465200964633377479145197038408116901327106468493831807000641577246417448908134495822028339761705905365398613527463662816881507291787145610182891716009505407072490691097943029471835157968113065071523597746984296197661560454442163361095634052138951650373193896962906203169809352467024247772052836999799731422581068645748537557874869718897034120634529002420631012358510111427944993245065350416694516913472010105229188198167306183788520891926236449848811955646933539477960935319919207451858981065765523367984374104834278565184338252025155136368869580505679884921590811310587077071610172673", 53 | "e": "115602723672843258810892161808995599340414281260248127600708536325470178701996999306086286379312077726886107268519700961209712187789855371", 54 | "v": "1250383260306407741656763352595256748825474237767244783206569756476708112785930898966696687140808011529311298553822794830872826226191807175199015541611342880032928005827271961840046208463350458298210749103878893742434685172894883857423865293195542824393317226300133796527531436931435189766065404966370796699897584860421160155369018136946091524266742514828667575397735892093187106092545876795688095293610064164136737808333322708435913545499149948994191514980395955519036106660001526586674248282052492138917987323789012051794441548696998993861159018178474063785171288325900474499496141522583368982451169653258746506425495702762445790848698570457196767532483566475068200091609719957656394696938689265240025099424248587121592521826940348286940172887963179718337593603053496022182071613592070622825622277436966372346642772481567879001423472517233061740522533372490151585309457871632521280719357505751796940152868034526426510835", 55 | "m": { 56 | "master_secret": "3455871040557234123393960708120725061759594951341120214330342075748561632734634451036095543889895409812764789858455375956895105746442946098665140470124325622343440794421325163223", 57 | "client_share": "4233663763294709836704307308997831519311512039775169744174375585917035614714239153287862168426091336550799195245481707264207548331415960277065672755643752404180562900805493953484" 58 | }, 59 | "m2": "12942698897200869280316481431207639453433287089474860040781378232999349549981799159560238504559317917040820580596635945161264308025301203452846862479261473387068350544024561412435" 60 | }, 61 | "ge_proofs": [] 62 | } 63 | }, 64 | { 65 | "primary_proof": { 66 | "eq_proof": { 67 | "revealed_attrs": { 68 | "jti_unique_identifier": "46414468020333259158238797309781111434265856695713363124410805958145233348633" 69 | }, 70 | "a_prime": "52825780315318905340996188008133401356826233601375100674436798295026172087388431332751168238882607201020021795967828258295811342078457860422414605408183505911891895360825745994390769724939582542658347473498091021796952186290990181881158576706521445646669342676592451422000320708168877298354804819261007033664223006892049856834172427934815827786052257552492013807885418893279908149441273603109213847535482251568996326545234910687135167595657148526602160452192374611721411569543183642580629352619161783646990187905911781524203367796090408992624211661598980626941053749241077719601278347846928693650092940416717449494816", 71 | "e": "40342480172543061520030194979861449480343743039487113094246205723322643070249538229638327935935486373873622430409109409257546971244601965", 72 | "v": "217871997575635857881367472262154388060800564043554848081521162883333745687724235201324121915821236796357195214089699645741515836727882126142579489701412861659136426497703162695983681701205672924385915403141611021784136285588350763399255203187442277784718461565122805239422370067600654500115262174706580098147603414365915243447789285877195068031630371954678432401446457453517813298670236942253026249413255471803997869331683293818651006043399070308083119054618677128448043841313844695654424369871669436628257531643623230026240200330490039607166147891705813033761093730859310423856156850596341547950105490585959768382544221555877471751940512766452511773683786023245283041103270102119125303027835868565240336923422734962345750992898991606841120358203160628015844345063465293475128118937815965000466081345494616126511595974927544434058100817176268040385848789013718618727873445834393897904247054897801708217939187593785671914", 73 | "m": { 74 | "iat_consent_timestamp": "7919242808448912829024078929834347184203169048480606699350973804205285806978474375691141504249426249676222104091995582731720654507393708298132400435805626192291975477967402460279", 75 | "master_secret": "3455871040557234123393960708120725061759594951341120214330342075748561632734634451036095543889895409812764789858455375956895105746442946098665140470124325622343440794421325163223", 76 | "data_controller": "16070549690575784944224634793654539357398383214512772967411296056738507137421264813779497172425030465490587794790393434847583852932544021088761347641812155158324233253206392974293", 77 | "notice": "2790610958721083178459621377821800672322230987466716467063649577108407884592339521820875278264969393963213925568888672412150769438560815981777952572004955362915245795447078373509", 78 | "sensitive": "13552814315985495030467505807226704038231487014593307078913973520081443107274508887651839292151852713782653522711975492131914644109941607616672243509214979259100892541150351227883", 79 | "services": "14860984314279608355643170908802532226194914773406547259519961082467311361623076451869406343140860447342041426195737612897540117192702117380288330928866665314831926780606136352645", 80 | "sub_subject_identifier": "11736177517163751882849070942823049196298287414132249166618760803125435466270948777194044507635346721244111946358927525083691171695431736819244809221351813271261283779276670885101", 81 | "moc_method_of_collection": "10026360820367693771310999595495505533281326977349798360729122862705999157070660881611421445424239119786180921960380892002204780026072600494332540208429642332890963846523547470729", 82 | "jurisdiction_data_processing": "15829143141425514118932461858094583045441924952665872659029333578019676797278419825311275014912077620757631693167948665554731430154156737419706553672424812320891308795411687679270", 83 | "iss_internet_processing_uri": "6900796243066434651671715348976599009606292569990892886896520779618011026060325075822786686418461731663661832508437549373109822105600719490952253743950241384782222356411498407620", 84 | "version_consent_specification": "7796257942256624260327966366702213561879098947042014532961291550019706546662478888172243088973621029223408695289700984802154645011280488167967047321149956253054269901250137513345", 85 | "policy_url": "12241676508867847022708464707584814145889660003604359058532137895063826021524887759921830911553663255421852525705197991376264187781979066233701110706958983099645275940668404311601" 86 | }, 87 | "m2": "6509130065158989037891281073557909501783443634141673890142284302459280804904096303151728187237486991775852971807701594247754409108836089746736345158069365449802597798950172729241" 88 | }, 89 | "ge_proofs": [] 90 | } 91 | } 92 | ], 93 | "aggregated_proof": { 94 | "c_hash": "81763443376178433216866153835042672285397553441148068557996780431098922863180", 95 | "c_list": [ 96 | [ 97 | 2, 98 | 122, 99 | 246, 100 | 66, 101 | 85, 102 | 35, 103 | 17, 104 | 213, 105 | 1 106 | ], 107 | [ 108 | 1, 109 | 162, 110 | 117, 111 | 246, 112 | 95, 113 | 154, 114 | 129, 115 | 32 116 | ] 117 | ] 118 | } 119 | }, 120 | "requested_proof": { 121 | "revealed_attrs": { 122 | "consent_attrs": { 123 | "sub_proof_index": 1, 124 | "raw": "205b1ea0-7848-48d4-b52b-339122d84f62", 125 | "encoded": "46414468020333259158238797309781111434265856695713363124410805958145233348633" 126 | } 127 | }, 128 | "revealed_attr_groups": { 129 | "biomarker_attrs_0": { 130 | "sub_proof_index": 0, 131 | "values": { 132 | "researcher_share": { 133 | "raw": "bf712cb328a92862b57f0dc806dec12a", 134 | "encoded": "101264834079306301897660576123112461042861436742738894013248454492965796383403" 135 | }, 136 | "unit": { 137 | "raw": "μM", 138 | "encoded": "38351211041892038382023569421847544683371072212679556578649761181279472893849" 139 | }, 140 | "concentration": { 141 | "raw": "10", 142 | "encoded": "10" 143 | }, 144 | "name": { 145 | "raw": "Iron", 146 | "encoded": "85547618788485118809771015708850341281587970912661276233439574555663751388073" 147 | }, 148 | "range": { 149 | "raw": "9.00-30.0", 150 | "encoded": "106828626115908025842177441696860557581575579893927923198365300598359723920768" 151 | }, 152 | "collected_on": { 153 | "raw": "2020-07-05", 154 | "encoded": "92231735610070911075924224447204218356256133056723930517696107260511721601349" 155 | }, 156 | "biomarker_id": { 157 | "raw": "c9ace7dc-0485-4f3f-b466-16a27a80acf1", 158 | "encoded": "33034450023603237719386825060766757598085121996569112944281451290292212516012" 159 | } 160 | } 161 | } 162 | }, 163 | "self_attested_attrs": {}, 164 | "unrevealed_attrs": {}, 165 | "predicates": {} 166 | }, 167 | "identifiers": [ 168 | { 169 | "schema_id": "CsQY9MGeD3CQP4EyuVFo5m:2:MYCO Biomarker:0.0.3", 170 | "cred_def_id": "CsQY9MGeD3CQP4EyuVFo5m:3:CL:14951:MYCO_Biomarker" 171 | }, 172 | { 173 | "schema_id": "FbozHyf7j5q7TDn2s8MXZN:2:MYCO Consent Enablement:0.1.0", 174 | "cred_def_id": "TUku9MDGa7QALbAJX4oAww:3:CL:531757:MYCO_Consent_Enablement" 175 | } 176 | ] 177 | } 178 | } -------------------------------------------------------------------------------- /data/W3CCredential.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 5 | ], 6 | "type": [ 7 | "VerifiableCredential", 8 | "AnonCredsCredential" 9 | ], 10 | "issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W", 11 | "issuanceDate": "2023-11-15T10:00:00.036203Z", 12 | "credentialSchema": { 13 | "type": "AnonCredsDefinition", 14 | "definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default", 15 | "schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0" 16 | }, 17 | "credentialSubject": { 18 | "firstName": "Alice", 19 | "lastName": "Jones", 20 | "age": "18" 21 | }, 22 | "proof": [ 23 | { 24 | "type": "AnonCredsProof2023", 25 | "signature": "AAAgf9w5.....8Z_x3FqdwRHoWruiF0FlM" 26 | }, 27 | { 28 | "type": "Ed25519Signature2020", 29 | "created": "2021-11-13T18:19:39Z", 30 | "verificationMethod": "did:sov:3avoBCqDMFHFaKUHug9s8W#key-1", 31 | "proofPurpose": "assertionMethod", 32 | "proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndSayn1PzZs6ZjWp1CktyGesjuTSwRdoWhAfGFCF5bppETSTojQCrfFPP2oumHKtz" 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /data/W3CCredentialWithRevocation.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 5 | ], 6 | "type": [ 7 | "VerifiableCredential", 8 | "AnonCredsCredential" 9 | ], 10 | "issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W", 11 | "issuanceDate": "2023-11-15T10:00:00.036203Z", 12 | "credentialSchema": { 13 | "type": "AnonCredsDefinition", 14 | "definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default", 15 | "schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0" 16 | }, 17 | "credentialStatus":{ 18 | "type":"AnonCredsCredentialStatusList2023", 19 | "id":"did:sov:3avoBCqDMFHFaKUHug9s8W:4:3avoBCqDMFHFaKUHug9s8W:3:CL:3avoBCqDMFHFaKUHug9s8W:2:basic_person:1.0:tag:CL_ACCUM:TAG_1" 20 | }, 21 | "credentialSubject": { 22 | "firstName": "Alice", 23 | "lastName": "Jones", 24 | "age": "18" 25 | }, 26 | "proof": [ 27 | { 28 | "type": "AnonCredsProof2023", 29 | "signature": "AAAgf9w5.....8Z_x3FqdwRHoWruiF0FlM" 30 | }, 31 | { 32 | "type": "Ed25519Signature2020", 33 | "created": "2021-11-13T18:19:39Z", 34 | "verificationMethod": "did:sov:3avoBCqDMFHFaKUHug9s8W#key-1", 35 | "proofPurpose": "assertionMethod", 36 | "proofValue": "z58DAdFfa9SkqZMVPxAQpic7ndSayn1PzZs6ZjWp1CktyGesjuTSwRdoWhAfGFCF5bppETSTojQCrfFPP2oumHKtz" 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /data/W3CPresentation.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 5 | ], 6 | "type": [ 7 | "VerifiablePresentation", 8 | "AnonCredsPresentation" 9 | ], 10 | "verifiableCredential": [ 11 | { 12 | "@context": [ 13 | "https://www.w3.org/2018/credentials/v1", 14 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 15 | ], 16 | "type": [ 17 | "VerifiableCredential", 18 | "AnonCredsCredential" 19 | ], 20 | "credentialSchema": { 21 | "type": "AnonCredsDefinition", 22 | "definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default", 23 | "schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0" 24 | }, 25 | "credentialSubject": { 26 | "firstName": "Alice", 27 | "age": [ 28 | { 29 | "type": "AnonCredsPredicate", 30 | "predicate": ">=", 31 | "value": 18 32 | } 33 | ] 34 | }, 35 | "issuanceDate": "2023-11-15T10:59:48.036203Z", 36 | "issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W", 37 | "proof": { 38 | "type": "AnonCredsPresentationProof2023", 39 | "proofValue": "eyJzdWJfcHJvb2Yi...zMTc1NzU0NDAzNDQ0ODUifX1dfX19" 40 | } 41 | } 42 | ], 43 | "proof": { 44 | "type": "AnonCredsPresentationProof2023", 45 | "challenge": "413296376279822794586260", 46 | "proofValue": "eyJhZ2dyZWdhdGVkIjp7ImNfaGFzaCI6IjEwMT...IsMzAsMTM1LDE4MywxMDcsMTYwXV19fQ==" 47 | } 48 | } -------------------------------------------------------------------------------- /data/W3CPresentationWithRevocation.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 5 | ], 6 | "type": [ 7 | "VerifiablePresentation", 8 | "AnonCredsPresentation" 9 | ], 10 | "verifiableCredential": [ 11 | { 12 | "@context": [ 13 | "https://www.w3.org/2018/credentials/v1", 14 | "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/data/anoncreds-w3c-context.json" 15 | ], 16 | "type": [ 17 | "VerifiableCredential", 18 | "AnonCredsCredential" 19 | ], 20 | "credentialSchema": { 21 | "type": "AnonCredsDefinition", 22 | "definition": "did:sov:3avoBCqDMFHFaKUHug9s8W:3:CL:13:default", 23 | "schema": "did:sov:3avoBCqDMFHFaKUHug9s8W:2:basic_person:0.1.0" 24 | }, 25 | "credentialStatus":{ 26 | "type":"AnonCredsCredentialStatusList2023", 27 | "id":"did:sov:3avoBCqDMFHFaKUHug9s8W:4:3avoBCqDMFHFaKUHug9s8W:3:CL:3avoBCqDMFHFaKUHug9s8W:2:basic_person:1.0:tag:CL_ACCUM:TAG_1" 28 | }, 29 | "credentialSubject": { 30 | "firstName": "Alice", 31 | "age": [ 32 | { 33 | "type": "AnonCredsPredicate", 34 | "predicate": ">=", 35 | "value": 18 36 | } 37 | ] 38 | }, 39 | "issuanceDate": "2023-11-15T10:00:00.036203Z", 40 | "issuer": "did:sov:3avoBCqDMFHFaKUHug9s8W", 41 | "proof": { 42 | "type": "AnonCredsPresentationProof2023", 43 | "proofValue": "eyJzdWJfcHJvb2Yi...zMTc1NzU0NDAzNDQ0ODUifX1dfX19" 44 | } 45 | } 46 | ], 47 | "proof": { 48 | "type": "AnonCredsPresentationProof2023", 49 | "challenge": "413296376279822794586260", 50 | "proofValue": "eyJhZ2dyZWdhdGVkIjp7ImNfaGFzaCI6IjEwMT...IsMzAsMTM1LDE4MywxMDcsMTYwXV19fQ==" 51 | } 52 | } -------------------------------------------------------------------------------- /data/anoncreds-w3c-context.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": { 3 | "@version": 1.1, 4 | "@protected": true, 5 | "ac": "https://anoncreds.example/2022/ns#", 6 | "xsd": "http://www.w3.org/2001/XMLSchema#", 7 | 8 | "AnonCredsCredential": "ac:AnonCredsCredential", 9 | 10 | "AnonCredsDefinition": { 11 | "@id": "ac:AnonCredsDefinition", 12 | "@context": { 13 | "@version": 1.1, 14 | "@protected": true, 15 | "definition": { 16 | "@id": "ac:definition", 17 | "@type": "@id" 18 | }, 19 | "schema": { 20 | "@id": "ac:schema", 21 | "@type": "@id" 22 | } 23 | } 24 | }, 25 | 26 | "AnonCredsCredentialStatusList2023": "ac:AnonCredsCredentialStatusList2023", 27 | 28 | "AnonCredsPresentation": "ac:AnonCredsPresentation", 29 | 30 | "AnonCredsPresentationProof2023": { 31 | "@id": "ac:AnonCredsPresentationProof2023", 32 | "@context": { 33 | "@version": 1.1, 34 | "@protected": true, 35 | "proofValue": { 36 | "@id": "ac:proofValue", 37 | "@type": "xsd:string" 38 | }, 39 | "challenge": { 40 | "@id": "ac:challenge", 41 | "@type": "xsd:string" 42 | } 43 | } 44 | }, 45 | 46 | "AnonCredsProof2023": { 47 | "@id": "ac:AnonCredsProof2023", 48 | "@context": { 49 | "@version": 1.1, 50 | "@protected": true, 51 | "signature": { 52 | "@id": "ac:signature", 53 | "@type": "xsd:string" 54 | } 55 | } 56 | }, 57 | 58 | "AnonCredsPredicate": { 59 | "@id": "ac:AnonCredsPredicate", 60 | "@context": { 61 | "@version": 1.1, 62 | "@protected": true, 63 | "predicate": { 64 | "@id": "ac:predicate", 65 | "@type": "xsd:string" 66 | }, 67 | "value": { 68 | "@id": "ac:value", 69 | "@type": "xsd:decimal" 70 | } 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 2 | const yargs = require('yargs/yargs') 3 | const { hideBin } = require('yargs/helpers') 4 | const argv = yargs(hideBin(process.argv)).argv; 5 | 6 | const fs = require('fs-extra'); 7 | const gulp = require('gulp'); 8 | const run = require('gulp-run'); 9 | const bump = require('gulp-bump'); 10 | const concat = require('gulp-concat'); 11 | const terser = require('gulp-terser'); 12 | const mergeStreams = require('merge-stream'); 13 | const cleanCSS = require('gulp-clean-css'); 14 | const axios = require('axios').default; 15 | const assets = fs.readJsonSync('./src/asset-map.json'); 16 | 17 | let compileLocation = 'assets/compiled'; 18 | 19 | async function fetchSpecRefs(){ 20 | return Promise.all([ 21 | axios.get('https://ghcdn.rawgit.org/tobie/specref/master/refs/ietf.json'), 22 | axios.get('https://ghcdn.rawgit.org/tobie/specref/master/refs/w3c.json'), 23 | axios.get('https://ghcdn.rawgit.org/tobie/specref/master/refs/whatwg.json') 24 | ]).then(async results => { 25 | let json = Object.assign(results[0].data, results[1].data, results[2].data); 26 | return fs.outputFile(compileLocation + '/refs.json', JSON.stringify(json)); 27 | }).catch(e => console.log(e)); 28 | } 29 | 30 | async function compileAssets(){ 31 | await fs.ensureDir(compileLocation); 32 | return new Promise(resolve => { 33 | mergeStreams( 34 | gulp.src(assets.head.css) 35 | .pipe(cleanCSS()) 36 | .pipe(concat('head.css')) 37 | .pipe(gulp.dest(compileLocation)), 38 | gulp.src(assets.head.js) 39 | .pipe(terser()) 40 | .pipe(concat('head.js')) 41 | .pipe(gulp.dest(compileLocation)), 42 | gulp.src(assets.body.js) 43 | .pipe(terser()) 44 | .pipe(concat('body.js')) 45 | .pipe(gulp.dest(compileLocation)) 46 | ).on('finish', function() { 47 | resolve(); 48 | }) 49 | }); 50 | } 51 | 52 | async function bumpVersion(){ 53 | return gulp.src('./package.json') 54 | .pipe(bump({ type: argv.v || 'patch' })) 55 | .pipe(gulp.dest('./')); 56 | } 57 | 58 | async function renderSpecs(){ 59 | return run('npm run render').exec() 60 | } 61 | 62 | gulp.task('refs', fetchSpecRefs); 63 | 64 | gulp.task('compile', compileAssets); 65 | 66 | gulp.task('publish', gulp.series(gulp.parallel(compileAssets, bumpVersion), renderSpecs)); 67 | 68 | gulp.task('watch', () => gulp.watch([ 69 | 'assets/**/*', 70 | '!assets/css/head.css', 71 | '!assets/js/head.js', 72 | '!assets/js/body.js' 73 | ], gulp.parallel('build'))); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | require('spec-up')(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "anoncreds-spec", 3 | "description": "AnonCreds Verifiable Credential Specification", 4 | "version": "0.1.0", 5 | "homepage": "https://wiki.hyperledger.org/display/ANONCREDS/AnonCreds+Specification+Working+Group", 6 | "license": "Apache 2", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/hyperledger/anoncreds-spec" 10 | }, 11 | "dependencies": { 12 | "spec-up": "git+https://github.com/andrewwhitehead/spec-up.git#fix-katex-path" 13 | }, 14 | "devDependencies": { 15 | "ace-custom-element": "1.6.5", 16 | "ajv": "^6.12.5", 17 | "mocha": "^10.1.0" 18 | }, 19 | "scripts": { 20 | "render": "node -e \"require('spec-up')({ nowatch: true })\"", 21 | "edit": "node -e \"require('spec-up')()\"", 22 | "test": "mocha 'test/**/*.js'" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spec/abstract.md: -------------------------------------------------------------------------------- 1 | ## Abstract 2 | 3 | The AnonCreds (Anonymous Credentials) specification is based on the open source verifiable credential 4 | implementation of AnonCreds that has been in use since 2017, initially as part of the 5 | [Hyperledger Indy](https://www.hyperledger.org/projects/hyperledger-indy) open 6 | source project and now in the [Hyperledger AnonCreds](https://wiki.hyperledger.org/display/anoncreds) project. The extensive use of AnonCreds around the world has made it a de 7 | facto standard for ZKP-based verifiable credentials, and this specification is the 8 | formalization of that implementation. 9 | 10 | 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](https://github.com/hyperledger/anoncreds-spec/blob/main/spec/ursaAnonCreds.pdf) which is the compiled pdf from their [official TeX document](https://github.com/hyperledger/ursa-docs/tree/main/specs/anoncreds1) published under CC4.0 license. 11 | -------------------------------------------------------------------------------- /spec/acknowledgements_authors.md: -------------------------------------------------------------------------------- 1 | ## Acknowledgements 2 | 3 | AnonCreds was initially created as part of the Open Source Hyperledger 4 | Indy project. 5 | 6 | This specification is the work of the AnonCreds Working Group, which includes dozens 7 | of active and dedicated participants. In particular, the following individuals 8 | contributed ideas, feedback, and wording that influenced this specification: 9 | 10 | * Artur Philipp - Technische Universität Berlin, IDUnion 11 | * Hakan Yildiz - Technische Universität Berlin 12 | * Matt Raffel - Kiva Microfiance 13 | 14 | ## Authors' Addresses 15 | 16 | ::: todo 17 | Add authors' addresses. 18 | ::: 19 | -------------------------------------------------------------------------------- /spec/anoncreds_conventions.md: -------------------------------------------------------------------------------- 1 | ## AnonCreds Conventions 2 | 3 | Over the years of using Hyperledger AnonCreds, several conventions (listed here) have been defined can or must be used 4 | in deploying AnonCreds. The conventions are not required in the current [AnonCreds implementation], but 5 | are necessary to follow for interoperability with other AnonCreds implementations. 6 | 7 | [AnonCreds implementation]: https://github.com/hyperledger/anoncreds-rs 8 | 9 | ### Encoding Credential Claims 10 | 11 | As described in this specification, the claim data that is actually signed in 12 | producing an AnonCreds verifiable credential is not the "raw", human-readable 13 | data of the claims, but rather an integer derived from the raw data. The act of 14 | encoding the data was defined to be done by the issuer. However, unless the 15 | issuer implements exactly the encoding expected by all others in an ecosystem, 16 | the signatures produced for a presentation will not verify. Thus, although the 17 | issuer is nominally in control of the encoding, practically, all issuers MUST 18 | follow the [encoding defined in this specification](#encoding-attribute-data). 19 | 20 | In a future version of AnonCreds we expect to move the encoding process away 21 | from the issuer and into AnonCreds. 22 | 23 | ### Date and Date/Time Predicates 24 | 25 | A powerful capability in AnonCreds is the ability to use predicates on dates, 26 | such as proving based on a date of birth (a strongly correlatable value) that a 27 | person is older than a certain age without revealing the date of birth. However, 28 | because of [how credential claims are encoded](#encoding-credential-claims) 29 | (above), for a date-based predicate to work, the date must be an integer. Thus, 30 | a "date of birth" claim in an [ISO 8601 Standard Date 31 | String](https://www.iso.org/iso-8601-date-and-time-format.html) will not be able 32 | to be used in a predicate. Rather, the convention of the AnonCreds community has 33 | been to put the data into the form of the date as an integer of value `YYYYMMDD` 34 | This convention was initially defined 35 | [here](https://github.com/hyperledger/aries-rfcs/tree/main/concepts/0441-present-proof-best-practices#dates-and-predicates) 36 | by the [Hyperledger Aries](https://www.hyperledger.org/projects/aries) 37 | community. 38 | 39 | For the same reasons, AnonCreds `datetime` claims that are to be used in predicates 40 | SHOULD be issued in [Unix Time](https://en.wikipedia.org/wiki/Unix_time) format. 41 | 42 | In a future version of AnonCreds we expect to define the type of each claim in a 43 | credential so that the `date` and `datetime` values as strings can be 44 | automatically encoded as integers and Unix Time values (respectively). This 45 | enables supporting both human-friendly displaying of the claims as well as 46 | support for predicates. 47 | 48 | ### Presentation Request Revocation Intervals 49 | 50 | While the AnonCreds [[ref: Presentation Request]] format allows the flexible 51 | application of `from` to `to` ranges for when the [[ref: Holder]] must prove 52 | their credential was not revoked, those deploying AnonCreds have found that it is 53 | rarely practical or necessary to use such flexibility, and the best practices 54 | are to set the two values (`from`, `to`) to be the same in [[ref: Presentation 55 | Requests]]. For [[ref: Verifiers]] interested in the current revocation status 56 | of the credential, both values should be set to the current time, while if the 57 | verifier wants to see the revocation status of the credential at some point in 58 | the past, both values should be set to point in time. 59 | 60 | Details about this convention can be found in the [Presentation Request section 61 | of this specification](#request-non-revocation-proofs). 62 | 63 | Since the [[ref:Holder]] must prove non-revocation based on a [[ref: Revocation 64 | Registry Entry]] published by the issuer, the actual interval that the [[ref: 65 | Holder]] must use is not `from` to `to`, but rather from the [[ref: Revocation 66 | Registry Entry]] active at time `from` to the [[ref: Revocation Registry Entry]] 67 | active at time `to`, where "time" is as determined by the transaction times 68 | recorded at the location on which the issuer published the [[ref: Revocation 69 | Registry]]. 70 | -------------------------------------------------------------------------------- /spec/anoncreds_methods.md: -------------------------------------------------------------------------------- 1 | ## AnonCreds Methods 2 | 3 | In the AnonCreds data flows are specifications of data models that contain 4 | identifiers to public AnonCreds objects ([[ref: Schemas]], [[ref: CredDefs]], 5 | [[ref: Revocation Registry Definitions]] and [[ref: Rev_Reg_Entrys]]) that are published by issuers 6 | to locations ([[ref: Verifiable Data Registries]] or VDRs) that must be 7 | accessible to holders and verifiers to enable presentation generation and 8 | verification. The format of the objects identifiers and the 9 | location of the objects are not defined in this specification. Rather, similar 10 | to the approach of [[ref: DID Methods]] defined in the [W3C DID 11 | Specification](https://www.w3.org/TR/did-core/), [[ref: AnonCreds methods]] 12 | allow for the registration and resolution mechanisms for AnonCreds objects 13 | across a range of VDRs. A registry of supported [[ref: AnonCreds methods]] can 14 | be found in the [AnonCreds Methods Registry](#anoncreds-methods-registry). 15 | 16 | Each [[ref: AnonCreds method]] specifies the format of the object identifiers, 17 | to what [[ref: Verifiable Data Registry]] the objects are published, how issuers 18 | register (publish) objects, and how issuers and verifiers can resolve the 19 | identifiers to retrieve the published objects. Implementations of agents 20 | (issuers, holders, verifiers) with AnonCreds support should be organized so as 21 | to allow issuers to use at least one [[ref: AnonCreds method]] for registration, 22 | and to allow holders and verifiers to use one or more [[ref: AnonCreds Methods]] 23 | for resolution. AnonCreds issuers will likely choose just a single AnonCreds 24 | registration method(s) they will use, and all AnonCreds participants will choose 25 | the set of AnonCreds resolvers they will require based on the issuers and types 26 | of credentials they want to support. As with DIDs, an external Universal 27 | AnonCreds Resolver is possible, as is a Universal AnonCreds Registrar. 28 | 29 | ### AnonCreds Identifiers 30 | 31 | AnonCreds identifiers MUST be a Uniform Resource Identifier (URI) 32 | conformant with [RFC3986](https://www.rfc-editor.org/rfc/rfc3986), although 33 | one notable exception is permitted. The exception is that for backwards 34 | compatibility, the AnonCreds identifiers used in the early (pre 35 | `did:indy`) open source Hyperledger Indy AnonCreds implementation are permitted. 36 | In the [AnonCreds Method Registry](#anoncreds-method-registry), 37 | this is the [Hyperledger Indy Legacy AnonCreds Method](https://hyperledger.github.io/anoncreds-methods-registry/#hyperledger-indy-legacy-anoncreds-method). 38 | 39 | ### Issuer Identifiers 40 | 41 | All AnonCreds objects that are published to a [[ref: Verifiable Data Registry]] ([[ref: Schema]], [[ref: Credential Definition]], [[ref: Revocation Registry Definition]], and [[ref: Revocation Status List]]) contain an `issuerId` reference. This identifier references the creator ([[ref: issuer]]) of the specific AnonCreds object. 42 | 43 | AnonCreds identifiers MUST be a Uniform Resource Identifier (URI) 44 | conformant with [RFC3986](https://www.rfc-editor.org/rfc/rfc3986), although 45 | one notable exception is permitted. The exception is that for backwards 46 | compatibility, the Indy DIDs used in the early (pre `did:indy`) open source 47 | Hyperledger Indy implementation are permitted. 48 | 49 | 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. 50 | 51 | ### Revocation Support 52 | 53 | Implementers only familiar with the "deltas"-style data format of Hyperledger Indy 54 | [[ref: RevRegEntries]] may not be aware that other VDRs may 55 | store the contents of each [[ref: RevRegEntry]] as 56 | "full state", meaning the status of each credential in the registry 57 | (revoked or not) is stored, vs. only the differences from the previous 58 | [[ref: RevRegEntry]] as in Hyperledger Indy. Either approach is fine 59 | as long as data is normalized by the AnonCreds method to the [[ref: RevReg]] 60 | format expected for AnonCreds [generate presentation](#generate-presentation) 61 | processing. This allows a AnonCreds Methods to trade-off the size of the 62 | [[ref: RevRegEntry]] in the VDR with the need for VDR-side processing to collect 63 | all of the deltas needed by the holder. 64 | 65 | An AnonCreds Method may opt to not support [[ref: revocation]] at all, and generate 66 | an error if the issuer attempts to create a [[ref: CredDef]] that includes revocation 67 | support. 68 | 69 | ### AnonCreds Method Registry 70 | 71 | The AnonCreds Method Registry is published 72 | [here](https://hyperledger.github.io/anoncreds-methods-registry/). The 73 | registry contains a description, metadata and a link to a specification for each 74 | AnonCreds Method submitted by its implementers/maintainers. The registry is a web page 75 | generated from [this 76 | repository](https://github.com/hyperledger/anoncreds-methods-registry). 77 | 78 | The AnonCreds Methods registry repository and published registry is 79 | managed by the AnonCreds Specification Working Group based on this [governance 80 | framework](https://hyperledger.github.io/anoncreds-methods-registry/#governance). 81 | 82 | Each entry in the [AnonCreds Method 83 | Registry](https://hyperledger.github.io/anoncreds-methods-registry/) 84 | links to a specification for the associated [[ref: AnonCreds objects method]]. 85 | The method specifications must include information about the AnonCreds identifiers 86 | used by the method, along with the mechanisms for AnonCreds objects registration 87 | and resolution. In some cases, the [[ref: AnonCreds method]] 88 | specification is defined within a [[ref: DID Method]] specification, while in 89 | other cases, the [[ref: AnonCreds method]] is a standalone 90 | specification. 91 | -------------------------------------------------------------------------------- /spec/data_flow_presentation_overview.md: -------------------------------------------------------------------------------- 1 | ## AnonCreds Presentation Data Flow 2 | 3 | ```mermaid 4 | sequenceDiagram 5 | autonumber 6 | participant L as Verifiable
    Data Registry 7 | participant SP as Schema Publisher 8 | participant I as Issuer 9 | participant H as Holder 10 | participant V as Verifier 11 | Note over L, V: AnonCreds Presentation Data Flow 12 | V->>V: Create presentation request 13 | V->>H: Send presentation request 14 | H->>H: Select credentials to satisfy the presentation request 15 | H->>L: If necessary: Request revocation entries 16 | L->>H: Return revocation entries 17 | H->>H: Generate presentation 18 | H->>V: Send presentation 19 | V->>L: Request credential definitions, revocation entries 20 | L->>V: Return credential definitions, revocation entries 21 | V->>V: Verify presentation 22 | ``` 23 | 24 | The flow of operations to request, create, and verify a verifiable presentation 25 | is illustrated in the [AnonCreds Presentation Data 26 | Flow](#anoncreds-presentation-data-flow) sequence diagram. 27 | 28 | The Verifier starts the process in step 1 by creating and sending a presentation 29 | request to the Holder. 30 | 31 | In step 2, the Verifier sends the presentation request to the Holder. 32 | 33 | In steps 3-6, the Holder collects the required information and creates the 34 | verifiable presentation to satisfy the presentation request received from the 35 | Verifier. If the Holder does not have the necessary credentials to satisfy the 36 | request, the Holder may ignore the presentation. 37 | 38 | In step 7, the Holder sends the verifiable presentation according to the 39 | presentation request to the Verifier. 40 | 41 | In step 8-10, the Verifier collects the required information and verifies the 42 | verifiable presentation and accepts it if the signature is valid, otherwise 43 | rejects the verifiable presentation. 44 | 45 | ::: todo 46 | Question: VDR access for schema, revocation etc. retrieval mandatory? 47 | ::: 48 | -------------------------------------------------------------------------------- /spec/data_flow_presentation_verify.md: -------------------------------------------------------------------------------- 1 | ### Verify Presentation 2 | 3 | In step 8, 9, and 10 of the [AnonCreds Presentation Data 4 | Flow](#anoncreds-presentation-data-flow), the [[ref: Verifier]] collects the required 5 | information necessary to verify the verifiable presentation, attempts to verify 6 | the proofs that make up the presentation and returns either a `true` if successful, 7 | and a `false` if any of the proofs fail, or if the presentation does not meet 8 | the presentation request. 9 | 10 | In the [previous section on presentation generation](#generate-presentation), 11 | the contents of the presentation is described. In verifying the presentation, 12 | each proof is extracted from the presentation and verified. The following 13 | sub-sections cover the verification of the proofs related to the source 14 | credentials (the `eq_proof`, any `ge_proof`s, and the `aggregate_proof`), and 15 | any non-revocation proofs in the presentation. 16 | 17 | For each source credential in the presentation, the [[ref: Verifier]] must 18 | retrieve (possibly from its cache, otherwise from the [[ref: VDR]]) the 19 | published [[ref: Schema]] and [[ref: Credential Definition]] based on the 20 | `schema_id` and `cred_def_id` values from the `identifiers` data item. For the 21 | non-revocation proof, additional issuer published data must be collected, as 22 | described below. 23 | 24 | While in this section we mostly focus on the verification of the proofs in the 25 | presentation, there are other data elements included, such as the revealed 26 | attributes, self-attested attributes, and the [[ref: Presentation Request]] for 27 | which the presentation was generated. Some of these values contribute to the 28 | verification process, as noted below. Finally, an important part of the 29 | verification process is **not** carried out in AnonCreds v1.0 and must be 30 | performed by the calling [[ref: verifier]]. We highlight that as well. 31 | 32 | #### Verify Validity Proofs 33 | 34 | An AnoncCreds validity proof is the combination of both equality and inequality predicate proofs. The validity proof is bound to the primary credential by the $\widehat{m_2}$ value that is presented in both proofs. The validity proof is verified by the following steps: 35 | 36 | - For each credential $C_p$, take each sub-proof $Pr_C$ and compute 37 | $$ \widehat{T} \leftarrow \left( 38 | \frac{Z} 39 | { \left( 40 | \prod_{j \in \mathcal{A}_r}{R_j}^{m_j} 41 | \right) 42 | (A')^{2^{596}} 43 | }\right)^{-c} 44 | (A')^{\widehat{e}} 45 | \left(\prod_{j\in (\mathcal{A}_{\widetilde{r}})}{R_j}^{\widehat{m_j}}\right) 46 | (S^{\widehat{v}})\pmod{n}. $$ 47 | Add $\widehat{T}$ to $\widehat{\mathcal{T}}$ . 48 | 49 | - For each predicate $p$: 50 | $$ \Delta' \leftarrow \begin{cases} 51 | z_j; & if\ * \equiv\ \leq 52 | z_j-1; & if\ * \equiv\ < 53 | z_j; & if\ * \equiv\ \geq 54 | z_j+1; & if\ * \equiv\ > 55 | \end{cases} $$ 56 | $$ 57 | a \leftarrow \begin{cases} 58 | -1 & if\ * \equiv \leq or < 59 | 1 & if\ * \equiv \geq or > 60 | \end{cases} 61 | $$ 62 | 63 | - Using $Pr_p$ and $\mathcal{C}$ compute 64 | $$ 65 | \widehat{T_i} \leftarrow T_i^{-c}Z^{\widehat{u_i}} S^{\widehat{r_i}}\pmod{n}_{1\leq i \leq 4}; 66 | \widehat{T_{\Delta}} \leftarrow \left(T_{\Delta}^{a}Z^{\Delta'}\right)^{-c}Z^{\widehat{m_j}}S^{a\widehat{r_{\Delta}}}\pmod{n}; 67 | \widehat{Q}\leftarrow (T_{\Delta}^{-c})\prod_{i=1}^{4}T_i^{\widehat{u_i}}(S^{\widehat{\alpha}})\pmod{n}, 68 | $$ 69 | and add these values to $\widehat{\mathcal{T}}$ in the order $\widehat{T_1},\widehat{T_2} ,\widehat{T_3},\widehat{T_4},\widehat{T_{\Delta}},\widehat{Q}$. 70 | 71 | #### Verify Non-Revocation Proof 72 | 73 | If the presentation includes one or more Non-Revocation Proofs (NRPs) the 74 | [[ref: verifier]] must also extract from the verifiable presentation the NRPs 75 | and process each of them. If any of the NRPs cannot be verified because one 76 | or more of the attributes/predicates came from a revoked credential, the 77 | overall status of the presentation is rejected as not verifiable. The following 78 | outlines the process for verifying an NRP. 79 | 80 | The [[ref: verifier]] begins by extracting from the section of the presentation 81 | for a given revocable credential the `non_revoc_proof` and `identifiers` data 82 | items. The [[ref: verifier]] must retrieve (possibly from its cache, otherwise 83 | from the [[ref: VDR]]) the published [[ref: RevRegEntry]] given the `rev_reg_id` 84 | and `timestamp` values from the `identifiers` data item. The [[ref: verifier]] 85 | extracts the `accumulator` item from the [[ref: RevRegEntry]] retrieved. Note 86 | that the [[ref: verifier]] does not need to collect the revocation status of all 87 | of the credentials in the registry, nor the contents of the tails file for the 88 | [[ref: RevReg]]. Only the issuer and [[ref: holder]] needs that data. During the 89 | verification process, the [[ref: verifier]] does not learn the index of the 90 | [[ref: holder]]'s credential in the [[ref: RevReg]]. 91 | 92 | Once the [[ref: verifier]] gets the data in the `non_revoc_proof` data item from 93 | the presentation for the NRP being processed, plus the accumulator from 94 | appropriate [[ref: RevRegEntry]], the following steps are carried out to verify 95 | the NRP. 96 | 97 | Calculation for NRP: 98 | 99 | $$\widehat{T_1} \leftarrow E^{c_H}\cdot h^{\widehat{\rho}} \cdot \widetilde{h}^{\widehat{o}} $$ 100 | $$\widehat{T_2} \leftarrow E^{\widehat{c}}\cdot h^{-\widehat{m}}\cdot\widetilde{h}^{-\widehat{t}}$$ 101 | $$\widehat{T_3} \leftarrow\left(\frac{e(h_0\mathcal{G},\widehat{h})}{e(A,y)} \right)^{c_H} \cdot e(A,\widehat{h})^{\widehat{c}}\cdot e(\widetilde{h},\widehat{h})^{\widehat{r}}\cdot e(\widetilde{h},y)^{-\widehat{\rho}}\cdot e(\widetilde{h},\widehat{h})^{-\widehat{m}}\cdot e(h_1,\widehat{h})^{-\widehat{m_2}}\cdot e(h_2,\widehat{h})^{-\widehat{s}}$$ 102 | $$\widehat{T_4} \leftarrow\left(\frac{e(\mathcal{G},\mathrm{acc})}{e(g,\mathcal{W})z}\right)^{c_H} \cdot e(\widetilde{h},\mathrm{acc})^{\widehat{r}}\cdot e(1/g,\widehat{h})^{\widehat{r'}}$$ 103 | $$\widehat{T_5} \leftarrow D^{c_H}\cdot g^{\widehat{r}}\widetilde{h}^{\widehat{o'}}$$ 104 | $$\widehat{T_6} \leftarrow D^{\widehat{r''}}\cdot g^{-\widehat{m'}} \widetilde{h}^{-\widehat{t'}}$$ 105 | $$\widehat{T_7} \leftarrow \left(\frac{e(pk\cdot\mathcal{G},\mathcal{S})}{e(g,g')}\right)^{c_H}\cdot e(pk\cdot \mathcal{G},\widehat{h})^{\widehat{r''}}\cdot e(\widetilde{h},\widehat{h})^{-\widehat{m'}}\cdot e(\widetilde{h},\mathcal{S})^{\widehat{r}}$$ 106 | $$\widehat{T_8} \leftarrow \left(\frac{e(\mathcal{G},u)}{e(g,\mathcal{U})}\right)^{c_H}\cdot e(\widetilde{h},u)^{\widehat{r}}\cdot e(1/g,\widehat{h})^{\widehat{r'''}}$$ 107 | 108 | Then all these values are added to $\widehat{T}$. This is then added with the validity proof which when hashed with $\mathcal{C}$ and $n_1$(received from [[ref: holder]]) re constructs the challenge hash $\widehat{c_H}$. 109 | If $\widehat{c_H} = c_H$, then the proof is valid. 110 | 111 | The NRP is bound to the primary credential by the $\widehat{m_2}$ value that is presented in both proofs. 112 | 113 | The verification code MUST surface to the [[ref: verifier]] if any part of the 114 | presentation, including any NRP(s), fail cryptographic verification. The 115 | verification code MAY surface additional detail about what part of the 116 | presentation failed, such as which NRP failed verification (if any). 117 | 118 | The [[ref: verifier]] SHOULD evaluate the presentation to make sure that the 119 | [[ref: holder]] provided all requested NRPs. Notably, if any expected NRPs 120 | are not received in the presentation, the [[ref: verifier]] SHOULD check to see 121 | if the given credential type is revocable. If not, it is acceptable that no 122 | NRP was received. However, if the credential used in the generation of the 123 | proof is revocable, and the [[ref: holder]] did not provide the NRP, the 124 | verification code SHOULD surface to the [[ref: verifier]] that the presentation 125 | failed cryptographic verification. 126 | 127 | #### Other Verification 128 | 129 | The AnonCreds verification code checks some additional non-cryptographic 130 | elements of the presentation. 131 | 132 | - That all of the requested attributes to be revealed are covered as either 133 | `revealed` or `unrevealed` attributes. Any missing attributes trigger a `false` verification. 134 | - That the non-revocation proofs (NRPs) meet the revocation interval requirements of the 135 | [[ref: Presentation Request]]. Note that the acceptable revocation interval may (and usually is) 136 | larger than the `from` and `to` values in the [[ref: Presentation Request]] as described [here](#request-non-revocation-proofs). 137 | 138 | #### Encoding Not Verified 139 | 140 | [[ref: Verifiers]] using AnonCreds 1.0 **MUST** verify that revealed attributes 141 | presented by the [[ref: Holder]] encode to the values signed by the [[ref: 142 | Issuer]]. AIf not done, a malicious [[ref: Holder]] could successfully 143 | substitute a different revealed attribute than what the issuer encoded and 144 | signed. 145 | 146 | As noted in the [issuance section of this 147 | specification](#encoding-attribute-data) the encoding of raw attribute data to 148 | the integers that are actually signed by the [[ref: Issuer]] is defined and 149 | handled by the [[ref: Issuer]], and is not defined in this specification, nor 150 | performed by the implementation. As such, the verification of the encoding is 151 | likewise delegated to the [[ref: Verifier]], enabling the risk to the verifier 152 | outlined above. 153 | -------------------------------------------------------------------------------- /spec/data_flow_revocation.md: -------------------------------------------------------------------------------- 1 | ## AnonCreds Revocation Data Flow 2 | 3 | AnonCreds includes a mechanism that supports the revocation of verifiable 4 | credentials. This mechanism includes: 5 | 6 | - An [[ref: issuer]] setting up to issue revocable credentials. 7 | - An [[ref: issuer]] issuing revocable credentials. 8 | - An [[ref: issuer]] activating or revoking issued credentials. 9 | - A [[ref: verifier]] requesting a presentation to include a non-revocation proof 10 | for one or more revocable credentials. 11 | - A [[ref: holder]] generating based on the presentation request of the verifier a 12 | non-revocation proof for attributes derived from revocable credentials. 13 | - A [[ref: verifier]] verifying a non-revocation proof included in a 14 | presentation from a [[ref: holder]]. 15 | 16 | A fundamental goal of AnonCreds is to not provide a correlatable identifier for 17 | either a [[ref: holder]] or a credential as part of generation and verification 18 | of an AnonCreds presentation. Applying that goal to revocation means that the 19 | revocation mechanism must support the [[ref: holder]] proving a credential used 20 | in generating a presentation is not revoked without providing a correlatable 21 | identifier for that credential or the holder itself. As such, the AnonCreds 22 | revocation mechanism uses a Zero Knowledge Proof (ZKP) that allows the [[ref: 23 | holder]] to prove a credential they hold is not revoked without revealing an 24 | identifier for their credential or the holder. 25 | 26 | ### AnonCreds Issuer Setup With Revocation 27 | 28 | The details of [[ref: issuer]] setting up revokable credential types are covered 29 | in the [issuer setup](#issuer-create-and-publish-revocation-registry-objects) 30 | section of this specification. Note the [warning and recommendation against the 31 | use of `ISSUANCE_ON_DEMAND`](#recommend-not-using-issuanceondemand) in that part 32 | of the specification. 33 | 34 | ### AnonCreds Issuance with Revocation 35 | 36 | The details of an [[ref: issuer]] issuing a revokable credential to a [[ref: 37 | holder]] are covered in the [issuance data 38 | flow](issue-credential) section of this specification. 39 | 40 | ### AnonCreds Credential Activation/Revocation and Publication 41 | 42 | When an [[ref: issuer]] decides to revoke a previously issued credential (or 43 | activate a previously inactive/revoked credential), they do so by publishing 44 | another instance of the [[ref: RevRegEntry]] object. Recall from the issuer 45 | setup section, the specification about [creating and publishing the first [[ref: 46 | RevRegEntry]]](data_flow_setup.md#creating-the-initial-revocation-registry-entry-object) 47 | for a [[ref: RevReg]]. In that process, the accumulator for the initial state of 48 | the [[ref: RevReg]] is published. When subsequent [[ref: RevRegEntry]] 49 | transactions are published to the ledger, each includes an updated value of the 50 | accumulator. The update of the accumulator is necessary with each revocation or 51 | (re)activation of a credential or set of credentials since the last published 52 | [[ref: RevRegEntry]]. This is because only the factors (all factors are listed 53 | in the respective tails file) of credentials which are active (meaning not being 54 | revoked) contribute to the accumulator. Therefore in addition to the updated 55 | accumulator value, every [[ref: RevRegEntry]] contains lists of indices of 56 | credential factors which have been either revoked or (re)activated within the 57 | [[ref: RevRegEntry]]. This list of factor indices is a so called [[ref: Witness 58 | Delta]] and enables the [[ref: Holder]] to successfully generate a proof of non 59 | revocation. 60 | 61 | An example of the 62 | data in the [[ref: RevRegEntry]] is shown in the following example of a [[ref: 63 | RevRegEntry]], pulled from [this transaction on the Sovrin 64 | MainNet](https://indyscan.io/tx/SOVRIN_MAINNET/domain/140326). 65 | 66 | ```json 67 | "data": { 68 | "revocDefType": "CL_ACCUM", 69 | "revocRegDefId": "4xE68b6S5VRFrKMMG1U95M:4:4xE68b6S5VRFrKMMG1U95M:3:CL:59232:default:CL_ACCUM:4ae1cc6c-f6bd-486c-8057-88f2ce74e960", 70 | "value": { 71 | "accum": "21 116...567", 72 | "prevAccum": "21 128...C3B", 73 | "issued": [ 74 | ], 75 | "revoked": [ 76 | 172 77 | ] 78 | } 79 | }, 80 | ``` 81 | 82 | In the above: 83 | 84 | - `revocDefType`: is defined by the comparable entry in the [[ref: RevReg]], and for this 85 | version of AnonCreds is hard-coded to `CL_ACCUM`. 86 | - `revocRegDefId`: is the Id of the [[ref: RevReg]] to which this entry is 87 | being added. 88 | - `accum`: is the new value of the accumulator based on the state of the 89 | credentials in the [[ref: RevReg]], including those listed in this transaction. The 90 | value is calculated by the Issuer based on the credential state changes, and 91 | submitted as part of the transaction, and verified by the ledger before being 92 | published. 93 | - `prevAccum`: is the previous value of the accumulator. The value is supplied 94 | by the Issuer in the transaction request, and verified by the ledger before 95 | being published. 96 | - `issued`: an array (possibly empty or not supplied) of the indices within the 97 | [[ref: RevReg]] of the credentials whose state has changed to `active` (also known as 98 | `not revoked`) since the last [[ref: RevRegEntry]] was published to the ledger. 99 | - `revoked`: an array (possibly empty or not supplied) of the indices within the 100 | [[ref: RevReg]] of the credentials whose state has changed to `revoked` (also known as 101 | `not active`) since the last [[ref: RevRegEntry]] was published to the ledger. 102 | 103 | In the example transaction above no credentials are `issued` (meaning changed 104 | from status `revoked` to `issued`) and only one, the credential with index 105 | `172`, is changed to `revoked`. Both lists can have an arbitrary number of 106 | entries, up to the total number of credentials in the [[ref: RevReg]]. 107 | 108 | The algorithm to calculate the value of a [[ref: RevRegEntry]] accumulator at 109 | any time is the same: determine the (modulo) product of the primes for each 110 | non-revoked credential in the [[ref: Revocation Registry]], as described 111 | [here](#creating-the-initial-revocation-registry-entry-object). 112 | 113 | ::: note 114 | 115 | The [[ref: issuer]] MUST track of the revocation status of all of the 116 | credentials within a [[ref: RevReg]] so that it can both calculate the correct 117 | accumulator and send to the [[ref: VDR]] accurate lists (`issued` and `revoked`) 118 | of the indices of the credentials whose status has changed since the last [[ref: 119 | RevRegEntry]] was published. If the list and accumulator published to [[ref: VDR]] get out of 120 | sync a [[ref: holder]] will not be able to generate a valid NRP. 121 | 122 | A [[ref: VDR]] publishing a [[ref: RevReg]] MAY perform its own calculation of 123 | the accumulator based on the list updates received in a [[ref: RevRegEntry]] 124 | transaction to ensure that the calculation of the accumulator after all of the 125 | revocation status updates to the credentials within the [[ref: RevReg]] have 126 | been applied, rejecting the transaction if the calculated accumulator does not 127 | match that from the [[ref: issuer]]. 128 | 129 | If an [[ref: issuer]]'s local revocation information gets out of sync with what 130 | is in the VDR, the [[ref: issuer]] MUST rationalize the differences and produce 131 | a [[ref: RevRegEntry]] transaction that accounts for both the last published 132 | [[ref: RevRegEntry]] published in the [[ref: VDR]] and the desired revocation 133 | status of all of the credentials in the [[ref: RevReg]]. 134 | 135 | ::: 136 | 137 | The [[ref: holder]] is not involved in the process of revoking a credential. 138 | There is no technical requirement for an [[ref: issuer]] to notify the [[ref: 139 | holder]] that a credential they were issued has been revoked. That said, it is a 140 | courtesy that may improve the user experience of the [[ref: holder]]. [Aries RFC 141 | 0183 Revocation 142 | Notification](https://github.com/hyperledger/aries-rfcs/tree/main/features/0183-revocation-notification) 143 | is an example of how that can be done. Even if not notified by the [[ref: 144 | issuer]] of the revocation of a credential, the [[ref: holder]] can detect their 145 | credential has been revoked when they retrieve the list of revoked credentials 146 | from the [[ref: VDR]] and discover the index of their credential in the list. 147 | 148 | ### AnonCreds Presentation Request with Revocation 149 | 150 | Carrying out an AnonCreds presentation with revocation is a two-step process, beginning with a 151 | request from the [[ref: verifier]] asking the [[ref: holder]] to include a 152 | non-revocation proof (NRP) in the presentation, and then the [[ref: holder]] 153 | creating the NRP and including it in the presentation sent to the [[ref: 154 | verifier]]. 155 | 156 | The verifier requesting a non-revocation proof, and the [[ref: holder]] 157 | generating the non-revocation proof are covered in the sections of this 158 | specification about [requesting](#request-non-revocation-proofs) and 159 | [generating](#generate-non-revocation-proofs) presentations, respectively. 160 | 161 | ### AnonCreds Verification with Revocation 162 | 163 | A [[ref: verifier]] receives the presentation from the [[ref: holder]] and 164 | processes the [non-revocation-related parts of the presentation](#verify-presentation) and 165 | the [revocation-related parts of the presentation](#verify-non-revocation-proof) 166 | (if any) in the presentation. The resulting status of the presentation combines the 167 | verification outcomes from processing all proofs within the presentation. If 168 | verification of one or more of the embedded proofs is unsuccessful, the 169 | presentation is rejected as unverifiable. 170 | -------------------------------------------------------------------------------- /spec/diagrams/anoncreds-visual-data-model-overview-simple-trust-triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/diagrams/anoncreds-visual-data-model-overview-simple-trust-triangle.png -------------------------------------------------------------------------------- /spec/diagrams/anoncreds-visual-data-model-overview-simple-trust-triangle.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/diagrams/anoncreds-visual-data-model-overview-simple-trust-triangle.pptx -------------------------------------------------------------------------------- /spec/diagrams/anoncreds-visual-data-model-overview-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/diagrams/anoncreds-visual-data-model-overview-simple.png -------------------------------------------------------------------------------- /spec/diagrams/setup-workflow.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | skinparam ParticipantPadding 20 3 | skinparam BoxPadding 20 4 | 5 | title Anoncreds 6 | scale 0.9 7 | 8 | 9 | box "Issuer" #LightBlue 10 | participant "Issuer" as IW 11 | actor Issuer as I 12 | endbox 13 | 14 | box "Prover" 15 | actor Prover as P 16 | participant "Prover" as PW 17 | endbox 18 | 19 | actor Verifier as V 20 | 21 | participant "Ledger" as L 22 | 23 | 24 | note over IW, L #white 25 | dashed arrows: a value from Ledger 26 | bold text: anoncreds libindy API call 27 | red: internal communication with walleted entity 28 | green: submit/get to/from secure wallet 29 | blue: submit/get to/from Ledger 30 | black: communication between Issuer/Prover/Verifier 31 | 32 | endnote 33 | 34 | 35 | === Create Credential Schema == 36 | I -> IW: 1. anoncreds_issuer_create_schema 37 | IW -> I: , 38 | 39 | I-[#blue]>L: send Schema txn 40 | 41 | === Create Credential Definition == 42 | I -[#blue]-> L: send get_schema req 43 | L -[#blue]-> I: 44 | I -> IW: 1. anoncreds_issuer_create_and_store_credential_def 45 | IW -[#green]> IW: store public/private keys and correctness proof 46 | IW -> I: , 47 | 48 | I-[#blue]>L: send Credential Definition txn 49 | 50 | === Create Revocation Registry == 51 | 52 | I -> IW: 3. anoncreds_issuer_create_and_store_revoc_reg 53 | IW -[#green]> IW: get keys 54 | IW -[#green]> IW: store revoc_reg_def, revoc_reg_accum, \npriv_key, tails_generator 55 | IW -> I: , , \n 56 | 57 | I-[#blue]>L: send REVOC_REG_DEF txn 58 | I-[#blue]>L: send REVOC_REG_ENTRY txn 59 | 60 | === Create Link secret == 61 | 62 | P -> PW: 5.anoncreds_prover_create_link_secret 63 | PW -[#green]> PW: store link secret 64 | PW -> P: 65 | @enduml -------------------------------------------------------------------------------- /spec/header.md: -------------------------------------------------------------------------------- 1 | AnonCreds Specification 2 | ================== 3 | 4 | **Specification Status**: v1.0 Draft 5 | 6 | **Latest Draft:** 7 | 8 | [https://github.com/hyperledger/anoncreds-spec](https://github.com/hyperledger/anoncreds-spec) 9 | 10 | **Editors:** 11 | 12 | - [Stephen Curran](https://github.com/swcurran) 13 | - Artur Philipp - Technische Universität Berlin, IDunion 14 | - Hakan Yildiz - Technische Universität Berlin, IDunion 15 | - Sam Curren 16 | - Victor Martinez Jurado 17 | - [Aritra Bhaduri](https://github.com/aritrocoder) 18 | - [Artem Ivanov](https://github.com/Artemkaaas) 19 | 20 | 21 | 22 | **Participate:** 23 | 24 | ~ [GitHub repo](https://github.com/hyperledger/anoncreds-spec) 25 | ~ [Commit history](https://github.com/hyperledger/anoncreds-spec/commits/main) 26 | ~ [Discord](https://discord.gg/hyperledger) 27 | 28 | ------------------------------------ 29 | -------------------------------------------------------------------------------- /spec/iana_considerations.md: -------------------------------------------------------------------------------- 1 | ## IANA Considerations 2 | 3 | This document has no IANA actions. -------------------------------------------------------------------------------- /spec/images/README.md: -------------------------------------------------------------------------------- 1 | # AnonCred Logos 2 | 3 | ![AnonCreds Logo](/spec/images/logo/hl_anoncreds_colour.svg) 4 | 5 | The set of AnonCreds logos found in this folder were created as a collaborative 6 | effort of the AnonCreds Specification Working Group and the Government of 7 | British Columbia. Are thanks in particular go to @alexgmetcalf and @knguyenBC 8 | for their creativity in developing these logos. 9 | 10 | The logos in this folder include a combination of: 11 | 12 | * Vertical and horizontal logos 13 | * White, black, green, grey and RGB logos 14 | * PNG, SVG and Abobe Illustrator (ai) logos 15 | 16 | © 2022. These logos are licensed under a [Creative Commons BY-ND 4.0 17 | license](https://creativecommons.org/licenses/by-nd/4.0/). 18 | -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/images/logo/hl_anoncreds_black.png -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_colour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/images/logo/hl_anoncreds_colour.png -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_colour.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/images/logo/hl_anoncreds_white.png -------------------------------------------------------------------------------- /spec/images/logo/hl_anoncreds_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /spec/informative_references.md: -------------------------------------------------------------------------------- 1 | ### Informative References 2 | 3 | ::: todo 4 | Add informative references 5 | ::: 6 | 7 | #### Resources on cryptography 8 | 9 | ##### Sigma protocols 10 | 11 | - The [original work](https://d-nb.info/1156214580/34) by Schnorr 12 | - [Cramer's thesis](https://ir.cwi.nl/pub/21438) that first defines the concept of Sigma protocol 13 | - set of [lecture notes](http://www.daimi.au.dk/~ivan/Sigma.pdf) on Sigma protocols 14 | - [book](https://link.springer.com/book/10.1007/978-3-642-14303-8) with a section on sigma protocols 15 | - [Blog post](https://medium.com/@loveshharchandani/zero-knowledge-proofs-with-sigma-protocols-91e94858a1fb) on Zero Knowledge Proofs with Sigma Protocols 16 | -------------------------------------------------------------------------------- /spec/introduction.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | 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: 4 | 5 | - A full implementation of the Layer 3 verifiable credential “Trust Triangle” of the [Trust over IP Model](https://trustoverip.org/wp-content/toip-model/). 6 | - Complete flows for issuing verifiable credentials (Issuer to Holder), and requesting, generating and verifying presentations of verifiable claims (Holder to Verifier). 7 | - Fully defined data models for all of the objects in the flows, including verifiable credentials, presentation requests and presentations sourced from multiple credentials. 8 | - Fully defined applications of cryptographic primitives. 9 | - The use of a Blind Signature scheme in the issuance process to enhance the privacy protections available to the holder recieving the credential, including: 10 | - Only the holder learns the final credential signature, the issuer only learns a blinded version which only the holder can unblind. 11 | - The issuer can sign messages blindly, never learning their value, while still being able to guarantee that the holder knows the value of the message being signed. This is used for the link secret, which the holder commits to during the issuance, the issuer blindly signs this message along with the rest of the credential attributes and then the holder removes the blinding to get a signature over the credential attributes including the unblinded link secret value. 12 | - 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: 13 | - Proving that certain values are part of a signed credential without revealing them including: credential signature, link secret and any attributes a holder does not wish to reveal. This helps prevent correlation based on these values. 14 | - The use of unrevealed identifiers for holder binding to prevent correlation based on such identifiers. 15 | - The use of predicate proofs to reduce the sharing of PII and potentially correlating data, especially dates (birth, credential issuance/expiry, etc.). 16 | - A revocation scheme that proves a presentation is based on credentials that have not been revoked by the issuers without revealing correlatable revocation identifiers. 17 | 18 | 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. 19 | 20 | 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. 21 | 22 | [comment]: <> (The diagram below resides currently here: https://docs.google.com/presentation/d/1sUT3AgMd288FG1bI5_WtIvWpmSta5pYbdui8zZ9Z2Tk) 23 | ![AnonCreds Data Model Overview](https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/spec/diagrams/anoncreds-visual-data-model-overview-simple-trust-triangle.png) 24 | 25 | AnonCreds require a [[ref: Verifiable Data Registry]] (VDR). A [[ref: VDR]] (box in green) is a public registry (often a ledger) used for storing some of the AnonCreds data objects. 26 | 27 | [[ref: Schemas]] are public and reusable templates, which define the attributes of issued AnonCreds [[ref: credentials]] and can be written (e.g. by an [[ref: Issuer]]) to the [[ref: VDR]]. 28 | 29 | Based on a [[ref: Schema]], arbitrary [[ref: Issuer]]s (box in yellow) can create a Credential Definition ([[ref: Credential Definition]]) which references the [[ref: Schema]]. A [[ref: Credential Definition]] enables [[ref: Issuers]] to issue AnonCreds [[ref: Credentials]] to [[ref: Holders]] and enables [[ref:Verifier]]s (box in red) to verify [[ref: Credentials]] issued to and presented by a [[ref:Holder]]. A [[ref: Credential Definition]] consists of two pieces of information: First, the [[ref: Private Credential Definition]] includes the private signing keys of the [[ref:Issuer]] for signing and issuing AnonCreds [[ref: Credentials]] to [[ref: holders]] and is kept private by the [[ref: Issuer]]. Second, the [[ref: Public Credential Definition]] includes the public keys of the [[ref:Issuer]], has to be stored on a [[ref:VDR]] and is used by [[ref: holders]] and arbitrary [[ref:Verifiers]] in order to verify AnonCreds [[ref: Credentials]] issued to and presented by [[ref: Holders]]. 30 | 31 | Each [[ref: Holder]] (box in blue) has a [[ref: link secret]], which enables [[ref: Credential]] to [[ref: Holder]] binding: Whenever a [[ref: Credential]] is issued to a [[ref: Holder]] by an [[ref: Issuer]], the [[ref: Holder]] generates a [[ref: blinding factor]] and uses this to commit to a blinded version of the [[ref: link secret]] which is sent to the [[ref: Issuer]]. The [[ref: Issuer]] verifies the commitment, before producing a blind signature over the blinded [[ref: link secret]] along with the other attributes within the AnonCreds [[ref: Credential]]. This blind signature is sent to the [[ref: Holder]], who removes the [[ref: blinding factor]] to retrieve a credential signature over the [[ref: Credential]] attributes including the unblinded [[ref: link secret]]. By using the same [[ref:link secret]] for every [[ref: Credential]] that is issued to the [[ref: Holder]], the [[ref: Holder]] can prove the affiliation of multiple [[ref:Credentials]] at presentation time. 32 | 33 | [[ref: Holders]] never present the raw signed credential data they - received from [[ref: Issuers]] - to [[ref: Verifiers]] for verification purposes. Instead a [[ref: Verifiable Presentation]] is created by the [[ref: Holder]] and sent to the [[ref: Verifier]]. A [[ref: Verifiable Presentation]] is a derivation of an AnonCreds [[ref: Credential]] which allows a [[ref: Holder]] to proof the correctness of the revealed credential data, without revealing the original raw credential signature(s). Additionally, [[ref: Holders]] prove knowledge the [[ref: link secret]] attribute within the [[ref: Credential]], without revealing this value to the [[ref: Verifiers]]. [[ref: Verifiers]] process [[ref: Verifiable Presentation]]s for verification of [[ref: credential]] data. 34 | 35 | AnonCreds allows the revocation of [[ref: Credentials]] issued to [[ref: Holders]] by [[ref: Issuers]]. In case revocation is required, at least one ([[ref: Revocation Registry Definition]]), which references the associated [[ref: Public Credential Definition]], has to be stored to the [[ref: VDR]] by the [[ref: Issuer]] in addition to the [[ref: Public Credential Definition]]. A [[ref: Revocation Registry Definition]] can have [[ref: Revocation Status List]]s. When one or more credentials have to be revoked, the [[ref: Issuer]] stores a [[ref: Revocation Status List]] with the updated status of the credentials in question to the [[ref: VDR]]. [[ref: Holder]] use these additional pieces of information in order to generate a [[ref:Non-Revocation Proof]]. A [[ref:Non-Revocation Proof]] proves to a [[ref:Verifier]], that the credential the [[ref:Holder]] presented to the [[ref:Verifier]], has not been revoked. [[ref: Verifiers]] use the information provided by a [[ref:Revocation Registry Definition]] and associated [[ref: Revocation Status List]]s to verify the [[ref: Holder]]`s [[ref:Non-Revocation Proof]]. A [[ref: Tails File]] supports the revocation mechanism. Each [[ref: Revocation Registry Definition]] requires exactly one Tails File. 36 | -------------------------------------------------------------------------------- /spec/normative_references.md: -------------------------------------------------------------------------------- 1 | ## References 2 | 3 | ### Normative References 4 | 5 | ::: todo 6 | Add normative references 7 | ::: 8 | -------------------------------------------------------------------------------- /spec/privacy_considerations.md: -------------------------------------------------------------------------------- 1 | ## Privacy Considerations 2 | 3 | The business expression of the AnonCreds privacy goal is to allow a verifiable 4 | credential holder to minimize the amount of information they share with others 5 | in presentations and to minimize the opportunities for holder [[ref: 6 | correlation]] (also called [[ref: unlinkability]]) across issuers and verifiers 7 | when using verifiable credentials and presentations. While it is understood that 8 | the [[ref: claims]] that a holder shares in a verifiable presentation may be 9 | correlatable, the act of providing an AnonCreds verifiable presentation must not 10 | provide [[ref: correlatable]] data. 11 | 12 | AnonCreds accomplishes its privacy goals using the following techniques, all of 13 | which are based on forms of [[ref: zero-knowledge proofs]], as described in this 14 | specification. 15 | 16 | - Holders use a [[ref: link secret]] to enable the binding of the credentials 17 | they receive from issuers, such that: 18 | - Issuers do not receive an identifier for the holder that can be correlated 19 | with other issuers during the credential issuance process. 20 | - In a presentation, verifiers receive proof of the holder's knowledge of the 21 | link secret without receiving an identifier that can be correlated with 22 | other issuers. 23 | - In a presentation, verifiers do not receive an identifier that can be 24 | correlated with the issuers of the source credentials. 25 | - In a presentation, holders prove all of the credentials they were issued are 26 | bound to the same link secret without revealing a correlatable identifier to 27 | verifiers. 28 | - In a presentation, the holder provides proof of the issuers signatures without 29 | revealing the signatures itself, which can be used as a correlatable 30 | identifier. 31 | - [[ref: Holders]] can (verifiably) selectively disclose [[ref: claims]] from 32 | source credentials. 33 | - [[ref: Holders]] can (verifiably) prove [[ref: predicate]] expressions about 34 | integer [[ref: claims]] from source credentials. 35 | - [[ref: Holders]] can in some situations, produce [[ref: non-revocation 36 | proofs]] (NRPs) about the source credentials in a presentation without 37 | revealing a correlatable identifier for themselves or the source credentials. 38 | - If credentials are both revocable and not revoked, the [[ref: Holder]] can 39 | produce a valid NRP for presented source credentials. 40 | - If credentials are both revocable and revoked, the [[ref: Holder]] cannot 41 | produce a valid NRP for presented source credentials. 42 | - If credentials are not revocable, the [[ref: Holder]] cannot produce a valid NRP 43 | for presented source credentials. 44 | 45 | The further privacy properties are stated according to [Section 5 of 46 | RFC6973](https://tools.ietf.org/html/rfc6973#section-5). 47 | 48 | ### Surveillance 49 | 50 | In the strict scope of this specification, the activities of the parties are not 51 | subject to surveillance due to the presentation [[ref: data minimization]] and 52 | [[ref: unlinkability]] characteristics of the credential issuance and presentation 53 | actions. However, in any digital trust ecosystem, there are other components 54 | that could lead to surveillance depending on how they are implemented. These 55 | include: 56 | 57 | - The interactions of the various participants could be surveilled depending on 58 | how the various objects (credentials, presentations, etc.) are exchanged. For 59 | example, HTTP traffic amongst [[ref: Issuers]], [[ref: Holders]] and [[ref: 60 | Verifiers]] could be correlated. 61 | - Using a secure, encrypted, peer-to-peer communication channel such as 62 | [DIDComm] can be used to mitigate the surveillance risk. 63 | - An implementation of AnonCreds based on this specification can not hide the 64 | time to generate or size of a presentation. 65 | - A deployment based on this implementation could mitigate this potential 66 | leakage by artificially inflating both the time to generate and the size of 67 | the presentation. 68 | - If the [[ref: Holder]] must request credential revocation information directly 69 | from an [[ref: Issuer]] when creating a presentation, the [[ref: Issuer]] 70 | could surveil the use of a credential by the [[ref: Holder]]. Further, if the 71 | [[ref: Verifier]] also must request revocation data from an [[ref: issuer]] to 72 | verify a received presentation, the [[ref: Issuer]] could correlate the use of 73 | credentials by [[ref: Holders]] and with what [[ref: Verifiers]] the 74 | credentials are being used. This is often called the [[ref: Call Home]] problem. 75 | - [[ref: Distributed Ledgers]] are often used in [[ref: Digital Trust ecosystems]] to 76 | mitigate such surveillance, where public data needed to generate and verify presentations 77 | are read from public ledgers operated by a set of "uninterested" parties. 78 | - Other techniques are possible to mitigate such surveillance when ledgers are 79 | not used. For example, [[ref: Verifiers]] requesting a presentation could 80 | retrieve the necessary revocation data from [[ref: Issuers]] and provide 81 | that data to the [[ref: Holder]]. The Issuer could still surveil the 82 | verifications occurring, but would not know what [[ref: Holders]] were 83 | providing the presentations. 84 | 85 | ### Stored Data Compromise 86 | 87 | The compromise of stored data held by the various agents in a digital trust 88 | ecosystem must be mitigated by the respective agent software and hardware, and 89 | is out of scope of this specification. The stored data of an individual agent 90 | shall be protected by implementing best practices in securing mobile wallet 91 | applications and IT infrastructure, like [ISO27001] and [Information Security 92 | Management] systems (ISMS). 93 | 94 | [ISO27001]: https://www.iso.org/standard/27001 95 | [Information Security Management]: https://en.wikipedia.org/wiki/Information_security_management 96 | 97 | ### Unsolicited Traffic 98 | 99 | The issue of unsolicited traffic is out of scope of this specification. It is a 100 | concern of the agents into which the AnonCreds library is embedded. The 101 | prevention of unsolicited traffic shall be accomplished by implementing best 102 | practices in securing mobile wallet applications and IT infrastructure, like 103 | [ISO27001] and [Information Security Management] systems (ISMS). 104 | 105 | ### Misattribution 106 | 107 | The risk of misattribution when using AnonCreds is mitigated by the participants 108 | following the specification. However, as noted in the [warning found in this 109 | section](#generating-a-credential-definition-without-revocation-support) of this 110 | specification, a malicious [[ref: issuer]] could deliberately generate a weak 111 | private key for use in issuing AnonCreds credentials such that a unique 112 | identifier for a holder can be determined via a brute force attack. In that 113 | case, anyone applying the brute force attack could issue credentials as it they 114 | were from the [[ref: Issuer]], possibly with false information. This risk 115 | further incentivize [[ref: Issuers]] not to deliberately weaken their keys. 116 | 117 | If a third party gains access to the secure storage of a [[ref: Holder]] (or a 118 | copy thereof), they could present information as if they were the [[ref: 119 | Holder]]. The stored data of an individual agent shall be protected by 120 | implementing best practices in securing mobile wallet applications and IT 121 | infrastructure, like [ISO27001] and [Information Security Management] systems 122 | (ISMS). 123 | 124 | ### Correlation 125 | 126 | As noted in the introduction to this section, AnonCreds v1 uses two important 127 | techniques to prevent correlation in the issuance and presentation of verifiable 128 | data: 129 | 130 | - The use of [[ref: zero knowledge proofs]] in eliminating an correlatable (linkable) 131 | data as part of the process of issuing AnonCreds verifiable credentials and 132 | presenting AnonCreds verifiable presentations. While the credential data 133 | issued and presented MAY include correlatable data elements, the issuing and 134 | presenting processes do not provide correlatable data elements. 135 | - The data minimization features supported in presenting data, such that the 136 | [[ref: holder]] can selectively disclose only relevant information from the 137 | credential based on the business purpose of the presentation, and the use of 138 | [[ref: predicates]] that support proving an expression based on an integer 139 | claim in a verifiable credential without revealing the claim itself. 140 | 141 | ### Identification 142 | 143 | AnonCreds v1 enables, but does not itself provide, identification. The [[ref: 144 | unlinkability]] and [[ref: data minimization]] capabilities inherent in 145 | AnonCreds enable the [[ref: Holder]] to provide presentations anonymously. 146 | However, the [[ref: claims]] within the presentation are from verifiably issued 147 | credentials, and as such, may be used for identification. 148 | 149 | ### Secondary Use 150 | 151 | The disclosed [[ref: claims]] and [[ref: predicates]] presented by the [[ref: 152 | Holder]] to the [[ref: Verifier]] are necessarily visible to the [[ref: 153 | verifier]]. The secondary use of that data is outside the scope of the AnonCreds 154 | specification, and is a governance issue. A [[ref: holder]] that presents data 155 | to a [[ref: verifier]] using AnonCreds cannot "revoke" that the presentation was 156 | made as the [[ref: verifier]] already possesses the disclosed data. 157 | 158 | ### Disclosure 159 | 160 | The disclosed [[ref: claims]] and [[ref: predicates]] presented by the [[ref: 161 | Holder]] to the [[ref: Verifier]] are necessarily visible to the [[ref: 162 | verifier]]. The disclosure of that data by the [[ref: verifier]] is outside the 163 | scope of the AnonCreds specification, and is a governance issue. A [[ref: 164 | holder]] that presents data to a [[ref: verifier]] using AnonCreds cannot 165 | "revoke" that the presentation was made as the [[ref: verifier]] already possesses the 166 | disclosed data. 167 | 168 | ### Exclusion 169 | 170 | The participants ([[ref: issuers]], [[ref: holders]], [[ref: verifiers]]) using 171 | AnonCreds may apply whatever policies (including refusal) they want in issuing, 172 | holding, requesting, presenting, and verifying AnonCreds verifiable credential 173 | and presentations. Such policies are out outside the 174 | scope of the AnonCreds specification, and are governance issues. 175 | -------------------------------------------------------------------------------- /spec/requirements_notations_conventions.md: -------------------------------------------------------------------------------- 1 | ## Requirements, Notation and Conventions 2 | 3 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL 4 | NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", 5 | "MAY", and "OPTIONAL" in this document are to be interpreted as 6 | described in BCP 14 [RFC2119] [RFC8174] when, and only when, they 7 | appear in all capitals, as shown here. 8 | -------------------------------------------------------------------------------- /spec/security_considerations.md: -------------------------------------------------------------------------------- 1 | ## Security Considerations 2 | 3 | There are a number of security considerations that issuers, holders, and 4 | verifiers should be aware of when processing data described by this 5 | specification. Ignoring or not understanding the implications of this section 6 | can result in security vulnerabilities. 7 | 8 | While this section attempts to highlight a broad set of security considerations, 9 | it is not a complete list. Implementers are urged to seek the advice of security 10 | and cryptography professionals when implementing mission critical systems using 11 | the technology outlined in this specification. 12 | 13 | ### Zero Knowledge Proofs in AnonCreds 14 | 15 | The security of AnonCreds is primarily based on the security of the AnonCreds 16 | cryptography, and in particular, the [[ref: zero knowledge proofs]] (ZKPs), upon 17 | which this specification is based. Each ZKP used in AnonCreds requires 18 | the following security properties be met, as introduced in many ZKP articles, 19 | such as this one on [non-interactive zero knowledge proofs]: 20 | 21 | - Completeness 22 | - If statement is true, a verifier will be convinced by prover. 23 | - Soundness 24 | - If statement is false, a cheating prover cannot convince verifier it is true 25 | except with some negligible probability. 26 | - Zero-Knowledge 27 | - The verifier learns nothing beyond the statement’s validity. 28 | 29 | [non-interactive zero knowledge proofs]: http://www0.cs.ucl.ac.uk/staff/J.Groth/ShortNIZK.pdf 30 | 31 | The security of the ZKPs is based on the security of RSA cryptography, and 32 | specifically that the factoring of `n`, where `n` is the product of two [[ref: 33 | safe primes]], is a computationally hard problem. 34 | 35 | These properties apply in the places where zero knowledge proofs are used in AnonCreds: 36 | 37 | - No linkable identifiers for the holder are shared to the issuer during the 38 | issuing process, yet the [[ref: issuer]] is convinced by the [[ref: holder]] 39 | that the [[ref: holder]] knows the [[ref: link secret]] to which the 40 | credentials are to be issued. 41 | - The [[ref: issuer]] may know other correlatable data about the [[ref: 42 | holder]], but not the [[ref: link secret]] to which the credential is 43 | issued. 44 | - No linkable identifiers for the holder are shared to the verifier during the 45 | presentation process, yet the [[ref: verifier]] is convinced by the [[ref: 46 | holder]] that the [[ref: holder]] knows the [[ref: link secret]] to which the 47 | credentials were issued. 48 | - The [[ref: verifier]] may receive [[ref: claims]] about the [[ref: holder]] 49 | that are correlatable, but not the [[ref: link secret]] to which the 50 | presented credentials were issued. 51 | - Even though the signatures over the credentials in a presentation are 52 | generated to be unique per presentation by the [[ref: holder]], the [[ref: 53 | verifier]] is convinced that the presented signatures were derived from the 54 | signatures generated by the [[ref: issuer]] using the cryptographic 55 | information in the [[ref: credential definitions]] published by the [[ref: 56 | issuers]]. 57 | - The [[ref: verifier]] is convinced that the signatures in the presentation are 58 | valid despite the selective disclosure of [[ref: claims]] from the verifiable 59 | credentials. 60 | - The [[ref: verifier]] is convinced that the presented predicates are true if 61 | and only if the requested predicate expression based on the [[ref: claim]] 62 | value is also true. 63 | - The [[ref: verifier]] is convinced that the [[ref: holders]] source verifiable 64 | credentials are not revoked (assuming it is revocable) if the [[ref: 65 | non-revocation proofs]] generated by the [[ref: issuer]] are valid. 66 | 67 | ### Eavesdropping 68 | 69 | The prevention of eavesdropping during the exchange of AnonCreds objects during 70 | issuance and verification is outside the scope of this specification. The 71 | security of the data shared between parties shall be protected by implementing 72 | best practices in communications amongst mobile wallet and IT infrastructure, 73 | like [ISO27001] and [Information Security Management] systems (ISMS). That said, 74 | the AnonCreds cryptography prevents an eavesdropper from gaining other than any 75 | plaintext information the parties of an interaction might intentionally or 76 | accidentally share. 77 | 78 | - Issuances are generated uniquely using nonces and the [[ref: holder]]'s 79 | generated [[ref: blinded link secret]] such that an eavesdropper that lacks 80 | knowledge of the holder's [[ref: link secret]] cannot replay the interaction 81 | or derive presentations from the verifiable credential. 82 | - Presentation requests are generated uniquely using a nonce, and presentations 83 | are derived based on the [[ref: holder]]'s [[ref: link secret]] such that an 84 | eavesdropper that lacks knowledge of the holder's [[ref: link secret]] cannot 85 | replay the interaction or derive additional presentations from the source 86 | verifiable credentials. 87 | 88 | ### Replay 89 | 90 | Replay prevention in AnonCreds for both issuances and presentations are 91 | prevented through the use of nonces. During the 3-step issuance process the 92 | [[ref: issuer]] (in the Credential Offer) and then the [[ref: holder]] (in the 93 | Credential Request) provide and verify the use of nonces before proceeding. 94 | Likewise in the presentation request, the [[ref: verifier]] provides a nonce 95 | that is incorporated by the [[ref: holder]] in generating the presentation, and 96 | verified by the [[ref: verifier]]. 97 | 98 | ### Message Tampering 99 | 100 | Message tampering during AnonCreds exchanges is ineffective when 101 | the secrets are securely protected by the [[ref: issuers]] and [[ref: holders]]. 102 | Arbitrary modification of AnonCreds data without access to the appropriate secret data is 103 | detectable through the failure of the verification of the data objects. See the 104 | security considerations sections about the [protection of 105 | data](#protection-of-data) and [protection of key 106 | material](#protection-of-key-material) for more on protecting those secrets and 107 | the potentials impacts if those secrets are disclosed. 108 | 109 | ### Holder Collusion 110 | 111 | [[ref: Holders]] that collude by sharing their [[ref: link secret]] could each 112 | be issued credentials to the same [[ref: link secret]]. Subsequently, 113 | such [[ref: holders]] could present any combination of the credentials together, 114 | including generating a proof that they were all issued to the same [[ref: link 115 | secret]]. Where such collusion is deemed a significant risk, such as with a 116 | mobile wallet application, the agent software should protect the [[ref: link 117 | secret]] so as to prevent access or extraction. [[ref: Issuers]] and [[ref: 118 | Verifiers]] may choose to implement verifications that the [[ref: holder]] is 119 | using a mobile wallet that is known to prevent such extraction and subsequent 120 | collusion. 121 | 122 | ### Protection of data 123 | 124 | The protection of data, both at rest and in motion, is outside the scope of this 125 | specification. Protection of data should be accomplished by the participants 126 | exchanging AnonCreds verifiable data implementing best practices in data 127 | protection for mobile wallet and IT infrastructure, like [ISO27001] and 128 | [Information Security Management] systems (ISMS). See the section on the 129 | [protection of key material](#protection-of-key-material) for more on the 130 | potential impact of disclosed secrets. 131 | 132 | When verifiable credentials are stored on a device and that device is lost or 133 | stolen, it might be possible for an attacker to use the victim's verifiable 134 | credentials. Mitigating the impacts of such a loss include: 135 | 136 | - Enabling password, pin, pattern, or biometric screen unlock protection on the 137 | device. 138 | - Enabling password, biometric, or multi-factor authentication for the 139 | credential repository. 140 | - Enabling password, biometric, or multi-factor authentication when accessing 141 | cryptographic keys. 142 | - All or any combination of the above. 143 | 144 | The potential risks in not adequately protecting data are covered in the 145 | [eavesdropping](#eavesdropping), [message insertion and 146 | modification](#message-insertion-and-modification) and [replay](#replay) 147 | subsection of the Security Considerations. 148 | 149 | ### Protection of Key Material 150 | 151 | The private keys associated with the public keys used by the [[ref: issuer]] 152 | must be kept secret. Each [[ref: issuer]] is responsible for storing and using 153 | their private keys and (for the [[ref: holder]]) the [[ref: link secret]] in a 154 | sufficiently secure manner. 155 | 156 | Unintended disclosure of [[ref: issuer]] secret information could allow others 157 | with access to the secrets issue credentials as if from the original [[ref: 158 | issuer]]. 159 | 160 | Unintended disclosure of the [[ref: holder]]'s [[ref: link secret]] could, if 161 | accompanied by the disclosure of the holder's verifiable credentials, allow 162 | others to present those credentials as their own. A malicious presenter could 163 | not present their own credentials issued to a different [[ref: link secret]] 164 | alongside the compromised verifiable credentials. 165 | 166 | ### Man-In-The-Middle 167 | 168 | The prevention and detection of Man-In-The-Middle (MITM) attacks during the 169 | exchange of AnonCreds objects during issuance and verification is outside the 170 | scope of this specification. Best practices in preventing MITM attacks while 171 | establishing the communications channel between the parties through which the 172 | data objects are exchanged should be followed by all of the participants. 173 | 174 | As covered in the previous section on [Message Insertion and 175 | Modification](#message-insertion-and-modification) issuance and presentations 176 | processes are not susceptible to alteration by a MITM. The primary risk of MITM 177 | attacks are the potential for collusion between [[ref: holders]] interacting 178 | with a [[ref: verifier]]. For example, a MITM interacts with a verifier to 179 | respond to a presentation request by colluding (in real-time) with a set of one 180 | or more [[ref: holders]] to pass on each presentation request and get a 181 | presentation from the most suitable [[ref: holder]] for each individual 182 | presentation request. This attack can be mitigated by requesting presentations 183 | that are satisfied from multiple source credentials, which will be verified to 184 | show all are bound to the same [[ref: link secret]]. 185 | 186 | ### Deletion 187 | 188 | The handling of the deletion of AnonCreds objects by the various participants is 189 | outside the scope of this specification. Such objects may be deleted by the 190 | participants at any time, understanding that once done, the operations enabled 191 | by the possession of those objects cannot be performed. For example, an issuer 192 | losing the issuance and revocation private keys can no longer issue or revoke 193 | credentials. Likewise, a [[ref: holder]] can't provide a presentation of a 194 | deleted source credential. Protection from inadvertent deletion of such data 195 | shall be protected by implementing best practices in data management by mobile 196 | wallet and IT infrastructure, like [ISO27001] and [Information Security 197 | Management] systems (ISMS). 198 | 199 | ### Denial of Service 200 | 201 | Denial of Service attacks against the various participants in AnonCreds 202 | exchanges are outside the scope of this specification. 203 | 204 | ### Storage or Network Amplification 205 | 206 | Storage or network amplification attacks against the various participants in 207 | AnonCreds exchanges are outside the scope of this specification. 208 | 209 | ## Residual Risks 210 | 211 | The residual risks inherent in AnonCreds include: 212 | 213 | - Compromise in the used cryptographic primitives used in AnonCreds v1, as 214 | described in this specification. 215 | - Bugs in the AnonCreds implementations used by participants exchanging 216 | AnonCreds verifiable data. 217 | - External libraries upon which the AnonCreds implementations are dependent. 218 | -------------------------------------------------------------------------------- /spec/status_copyright_toc.md: -------------------------------------------------------------------------------- 1 | ## Status of This Memo 2 | 3 | This is a proposal for version v1.0 of AnonCreds which aims at AnonCreds being ledger agnostic. 4 | 5 | This document is a product of the [AnonCreds Working Group](https://github.com/hyperledger). 6 | It represents the consensus of the AnonCreds community. 7 | The proposal for v1.0 has partly been worked out at the [RWOT2022](https://rebootthehague.com/) event in the Hague, Netherlands. 8 | 9 | Information about the current status of this document, any errata, 10 | and how to provide feedback on it may be obtained at 11 | [https://github.com/hyperledger/anoncreds-spec](https://github.com/hyperledger/anoncreds-spec). 12 | 13 | ## Copyright Notice 14 | 15 | This specifications is subject to the **Community Specification License 1.0** 16 | available at 17 | [https://github.com/CommunitySpecification/1.0](https://github.com/CommunitySpecification/1.0). 18 | 19 | If source code is included in the specification, that code is subject to the 20 | Apache 2.0 license unless otherwise marked. In the case of any conflict or 21 | confusion within this specification between the Community Specification License 22 | and the designated source code license, the terms of the Community Specification 23 | License shall apply. 24 | -------------------------------------------------------------------------------- /spec/ursaAnonCreds.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/anoncreds-spec/2cc439145c3a83bb6d7564a567e44b0242a814e5/spec/ursaAnonCreds.pdf -------------------------------------------------------------------------------- /specs.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "specs": [ 4 | { 5 | "title": "AnonCreds Specification", 6 | "spec_directory": "./spec", 7 | "output_path": "./docs", 8 | "markdown_paths": [ 9 | "header.md", 10 | "abstract.md", 11 | "status_copyright_toc.md", 12 | "introduction.md", 13 | "requirements_notations_conventions.md", 14 | "terminology.md", 15 | "data_flow_setup.md", 16 | "data_flow_issuance.md", 17 | "data_flow_presentation_overview.md", 18 | "data_flow_presentation_create_request.md", 19 | "data_flow_presentation_create_presentation.md", 20 | "data_flow_presentation_verify.md", 21 | "data_flow_revocation.md", 22 | "anoncreds_methods.md", 23 | "w3c_representation.md", 24 | "anoncreds_conventions.md", 25 | "iana_considerations.md", 26 | "security_considerations.md", 27 | "privacy_considerations.md", 28 | "normative_references.md", 29 | "informative_references.md", 30 | "acknowledgements_authors.md" 31 | ], 32 | "logo": "https://raw.githubusercontent.com/hyperledger/anoncreds-spec/main/spec/images/logo/hl_anoncreds_colour.svg", 33 | "logo_link": "https://github.com/hyperledger/anoncreds-spec", 34 | "katex": true, 35 | "source": { 36 | "host": "github", 37 | "account": "hyperledger", 38 | "repo": "anoncreds-spec" 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /src/asset-map.json: -------------------------------------------------------------------------------- 1 | { 2 | "head": { 3 | "css": [ 4 | "assets/css/custom-elements.css", 5 | "assets/css/prism.css", 6 | "assets/css/chart.css", 7 | "assets/css/index.css" 8 | ], 9 | "js": [ 10 | "assets/js/utils.js", 11 | "assets/js/custom-elements.js" 12 | ] 13 | }, 14 | "body": { 15 | "js": [ 16 | "assets/js/markdown-it.js", 17 | "assets/js/prism.js", 18 | "assets/js/mermaid.js", 19 | "assets/js/chart.js", 20 | "assets/js/font-awesome.js", 21 | "assets/js/popper.js", 22 | "assets/js/tippy.js", 23 | "assets/js/index.js" 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /src/markdown-it-extensions.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const levels = 2; 4 | const openString = '['.repeat(levels); 5 | const closeString = ']'.repeat(levels); 6 | const contentRegex = /\s*([^\s\[\]:]+):?\s*([^\]\n]+)?/i; 7 | 8 | module.exports = function(md, templates = {}) { 9 | 10 | md.inline.ruler.after('emphasis', 'templates', function templates_ruler(state, silent) { 11 | 12 | var start = state.pos; 13 | let prefix = state.src.slice(start, start + levels); 14 | if (prefix !== openString) return false; 15 | var indexOfClosingBrace = state.src.indexOf(closeString, start); 16 | 17 | if (indexOfClosingBrace > 0) { 18 | 19 | let match = contentRegex.exec(state.src.slice(start + levels, indexOfClosingBrace)); 20 | if (!match) return false; 21 | 22 | let type = match[1]; 23 | let template = templates.find(t => t.filter(type) && t); 24 | if (!template) return false; 25 | 26 | let args = match[2] ? match[2].trim().split(/\s*,+\s*/) : []; 27 | let token = state.push('template', '', 0); 28 | token.content = match[0]; 29 | token.info = { type, template, args }; 30 | if (template.parse) { 31 | token.content = template.parse(token, type, ...args) || token.content; 32 | } 33 | 34 | state.pos = indexOfClosingBrace + levels; 35 | return true; 36 | } 37 | 38 | return false; 39 | }); 40 | 41 | md.renderer.rules.template = function(tokens, idx, options, env, renderer) { 42 | let token = tokens[idx]; 43 | let template = token.info.template; 44 | if (template.render) { 45 | return template.render(token, token.info.type, ...token.info.args) || (openString + token.content + closeString); 46 | } 47 | return token.content; 48 | } 49 | 50 | let pathSegmentRegex = /(?:http[s]*:\/\/([^\/]*)|(?:\/([^\/?]*)))/g; 51 | md.renderer.rules.link_open = function(tokens, idx, options, env, renderer) { 52 | let token = tokens[idx]; 53 | let attrs = token.attrs.reduce((str, attr) => { 54 | let name = attr[0]; 55 | let value = attr[1]; 56 | if (name === 'href') { 57 | let index = 0; 58 | value.replace(pathSegmentRegex, (m, domain, seg) => { 59 | str += `path-${index++}="${domain || seg}"`; 60 | }); 61 | } 62 | return str += name + '="' + value + '" '; 63 | }, ''); 64 | let anchor = ``; 65 | return token.markup === 'linkify' ? anchor + '' : anchor; 66 | } 67 | 68 | md.renderer.rules.link_close = function(tokens, idx, options, env, renderer) { 69 | return tokens[idx].markup === 'linkify' ? '' : ''; 70 | } 71 | 72 | }; --------------------------------------------------------------------------------