Trust Registry Spec v1.0

The goal of this document is to define a minimal viable product (production-ready functionality) that satisfies our ecosystem's requirements, with an awareness of potential future improvements and alignment with the ToIP trust registry protocol (or any other trust registry protocol we find interesting). The goal is not to define or implement a protocol. An essential part of this effort is defining how the service will be developed, deployed, and operated.

In our case, we currently need to implement only the following two parts from ToIP v1 protocol specification:

  1. Which issuers are authorized to issue what types of verifiable credentials.
  2. Which verifiers are authorized to request what types of verifiable presentations.

The governance framework is not part of this document. We assume a governance framework will describe the rules to answer the questions above. The trust registry is just a technical implementation of such rules.

User Stories

As an Issuer/Verifier, I want to request Governing Authority for addition to the trust registry with my identifier and information about my entity, so that I can participate in the ecosystem as an Issuer/Verifier.

As a Governing Authority, I want to be able to add an issuer or verifier, so that I'm the only one who controls the data and I can fulfill my obligation to keep the validity and authenticity of the registry.

As a Holder, I want to know who are authorized issuers for specific credentials, so that I’m not misled that I have a correct credential but later verification would fail because the credential was issued by an illegitimate issuer.

As a Verifier, I want to know who are authorized issuers of a particular credential type, so that I can request presentation with restrictions for such credential types from defined issuers.

As a Holder, I want to know who are authorized verifiers for a any credential type, so that I can answer a presentation request only to those verifiers and don't share my personal data with a fraudulent entity. We intentionaly don't want to specify authorized verifiers for specific credential type. We assume that all authorized verifiers inside the registry are known and have been vetted by Governing Authority.

As an Issuer/Verifier, I want to be able to update information about my entity (by myself?), so that I can change the information and keep them updated in the registry (without asking Governing Authority). This is not needed in the first iteration.

Technical Elaboration

  • Governing Authority is Bankserv.
  • Credential format is AnonCreds.
  • The credential type is AnonCreds credential definition which automatically ties an issuer to a particular AnonCreds schema. If the verifier credentials are defined by credential definitions then it directly answers the issuer of a particular credential type. This approach kills two birds with one stone, however, it might require more complexity on the implementation side. The Verifier needs to get credential schema based on the credential definition before they create a presentation request.
  • The registry should also keep a list of schemas that issuers can issue, therefore, add their credential definition for it. The list should originate from https://github.com/bsaiamza/Iamza_digitalid_docs.
  • The entity identifier is DID, starting with did:sov. We can eventually allow did:web for verifiers, therefore, they don't need to write did to the ledger. What other types should we consider?
  • The service will be publicly available via REST API for reading.
  • It's likely that there must be a UI to manage the service from the Governing Authority.

API

The API is inspired by APIs from DIDx didx-registry.json, Absa absa-registry.json and ToIP Trust Registry v1 Open API. I separated out the list of credential types from an entity as it was in DIDx API. If I understood it correctly, it would allow issuers only to verify the same credential type as they're issuing. This might be fine for the first iteration of the trust registry service but quite limiting later. On the other hand, if we keep this information separate, the issuer will likely have duplicated definitions in both the issuer and verifier list of credential types.

GET /issuers/did:sov:Enmy7mgJopSsELLXd9G91d

List of credential types that an issuer identified by DID is authorized to issue. We can return not only the list of such credential types but also all issuer attributes.

{
  "id": "8fa665b6-7fc5-4b0b-baee-6221b1844ec8",
  "name": "Yoma123",
  "did": "did:sov:Enmy7mgJopSsELLXd9G91d",
  "logo_url": "https://yoma.africa/images/sample.png1",
  "domain": "www.abc.xyz12",
  "registered_at": "2023-05-24T18:14:24",
  "updated_at": "2023-05-24T18:41:08",
  "role": "issuer",
  "credentials": [
    "test_schema4:Enmy7mgJopSsELLXd9G91d:3:CL:24:default",
    "test_schema5:Enmy7mgJopSsELLXd9G91d:3:CL:27:default",
    "Proof of Person:Enmy7mgJopSsELLXd9G91d:3:CL:30:default"
  ]
}

GET /verifiers/did:sov:DZFXtbRTEud9YLKN7bBmDb

List of credential types that a verifier identified by DID is authorized to request. We can return not only the list of such credential types but also all verifier attributes.

{
  "id": "fb38e13f-63e0-4cb6-980c-8c2fc04cbfae",
  "name": "Yoma",
  "did": "did:sov:DZFXtbRTEud9YLKN7bBmDb",
  "logo_url": "https://yoma.africa/images/sample.pngkhjjkh",
  "domain": "www.abc.xyz67868869",
  "registered_at": "2023-05-24T21:39:52",
  "updated_at": "2023-05-24T21:40:50",
  "role": "verifier",
  "verifications": [
      "FICA",
      "RICA"
  ]
}

GET /schemas

List of schemas that issuers can be authorized to issue and verifiers to request.

[
  "Mnj3wB4tgrww6RETzZVx64:2:test_schema:0.3.0",
  "Mnj3wB4tgrww6RETzZVx64:2:test_schema1:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema1:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema2:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema3:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema4:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:test_schema5:0.3.0",
  "BrAQHowoF4rxmr92T8mjWB:2:Proof of Person:0.3.0",
  "Cmj9d7pwxEj2fYrKpNmtGx:2:test_schema:0.3.0"
]

GET /verification_policies - latest versions

GET /verification_policies?policy_id=x?history=true?version=1.0.1 - provide historical versions of verification policies to proof that governance was adhered to at a point back in time

List of verification policies for specific industry verification such as FICA, RICA that verifiers can use to verify requests.

[
    {
        "FICA": {
  "proof_request": {
    "requested_attributes": {
      "additionalProp1": {
        "name": "string",
        "names": [
          "string"
        ],
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "did:absa, did:fnb, did:sbsa",
            "additionalProp2": "did:municipality, did:bank",
            "additionalProp3": "string"
          }
        ]
      },
      "additionalProp2": {
        "name": "string",
        "names": [
          "string"
        ],
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "string",
            "additionalProp2": "string",
            "additionalProp3": "string"
          }
        ]
      },
      "additionalProp3": {
        "name": "string",
        "names": [
          "string"
        ],
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "string",
            "additionalProp2": "string",
            "additionalProp3": "string"
          }
        ]
      }
    },
    "requested_predicates": {
      "additionalProp1": {
        "name": "string",
        "p_type": "<",
        "p_value": 0,
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "string",
            "additionalProp2": "string",
            "additionalProp3": "string"
          }
        ]
      },
      "additionalProp2": {
        "name": "string",
        "p_type": "<",
        "p_value": 0,
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "string",
            "additionalProp2": "string",
            "additionalProp3": "string"
          }
        ]
      },
      "additionalProp3": {
        "name": "date_of_birth",
        "p_type": ">",
        "p_value": 18,
        "non_revoked": {
          "from": 0,
          "to": 0
        },
        "restrictions": [
          {
            "additionalProp1": "string",
            "additionalProp2": "string",
            "additionalProp3": "string"
          }
        ]
      }
    },
    "name": "string",
    "non_revoked": {
      "from": 0,
      "to": 0
    },
    "nonce": "random(uuid)",
    "version": "1.0.1"
  },
  "comment": "FICA",
  "protocol_version": "v1"
}
    }
]

GET /registry

The whole content of the registry. The idea is that a holder's edge agent can download it and cache it on a device where it runs. The data are normilzed, entities are identified by IDs and credential types are defined in separate arrays. Thefore we don't duplicate information about entities as I mentioned above.

{
  "entities": [
    {
      "id": "bd368051-0843-4efe-b7e3-24ed6c5fdd9f",
      "name": "Yoma10",
      "did": "did:sov:9yyYk3D6mmk9NtzEG1QZkK",
      "logo_url": "https://yoma.africa/images/sample.png3",
      "domain": "www.3.xyz",
      "registered_at": "2023-05-24T17:58:31",
      "updated_at": "2023-05-24T17:58:31"
    },
    {
      "id": "8fa665b6-7fc5-4b0b-baee-6221b1844ec8",
      "name": "Yoma123",
      "did": "did:sov:Enmy7mgJopSsELLXd9G91d",
      "logo_url": "https://yoma.africa/images/sample.png1",
      "domain": "www.abc.xyz12",
      "registered_at": "2023-05-24T18:14:24",
      "updated_at": "2023-05-24T18:41:08"
    },
    {
      "id": "eb3ac961-5fd3-45fa-acfe-1ea296e3fff5",
      "name": "Yom123123a",
      "did": "did:sov:EuKgs98XkUSELo1ioqUh3U",
      "logo_url": "https://yoma.africa/images/sample.png123123",
      "domain": "www.abc.xyz123123",
      "registered_at": "2023-05-24T20:19:44",
      "updated_at": "2023-05-24T20:19:44"
    },
    {
      "id": "fb38e13f-63e0-4cb6-980c-8c2fc04cbfae",
      "name": "Yoma",
      "did": "did:sov:DZFXtbRTEud9YLKN7bBmDb",
      "logo_url": "https://yoma.africa/images/sample.pngkhjjkh",
      "domain": "www.abc.xyz67868869",
      "registered_at": "2023-05-24T21:39:52",
      "updated_at": "2023-05-24T21:40:50".
      "credentials": [],
      "verifications": []
    }
  ],
  "issuers": [
    {
      "id": "8fa665b6-7fc5-4b0b-baee-6221b1844ec8",
      "credentials": [
        "test_schema4:Enmy7mgJopSsELLXd9G91d:3:CL:24:default",
        "test_schema5:Enmy7mgJopSsELLXd9G91d:3:CL:27:default",
        "Proof of Person:Enmy7mgJopSsELLXd9G91d:3:CL:30:default"
      ]
    }
  ],
  "verifiers": [
    {
      "id": "fb38e13f-63e0-4cb6-980c-8c2fc04cbfae",
      "credentials": ["test_schema:DZFXtbRTEud9YLKN7bBmDb:3:CL:12:default"]
    }
  ],
  "schemas": [
    "Mnj3wB4tgrww6RETzZVx64:2:test_schema:0.3.0",
    "Mnj3wB4tgrww6RETzZVx64:2:test_schema1:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema1:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema2:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema3:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema4:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema5:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:Proof of Person:0.3.0",
    "Cmj9d7pwxEj2fYrKpNmtGx:2:test_schema:0.3.0"
  ],
  "verification policies": [
    "Mnj3wB4tgrww6RETzZVx64:2:test_schema:0.3.0",
    "Mnj3wB4tgrww6RETzZVx64:2:test_schema1:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema1:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema2:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema3:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema4:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:test_schema5:0.3.0",
    "BrAQHowoF4rxmr92T8mjWB:2:Proof of Person:0.3.0",
    "Cmj9d7pwxEj2fYrKpNmtGx:2:test_schema:0.3.0"
  ]
}

Open Issues/Questions:

  • I natuarally used the term "entity" instead of "actor", but I'm happy to change it if the "actor" is really the correct one. We decided to use entity for now.
  • What information about an entity should be part of the registry?
  • Out of scope of trust registry: Should our implementation on the consumer side be restricted to only allow interaction with authorized entities?
  • What's the role of Governing Authority? I assume that Governing Authority should decide not only what DID can be added to the list of entities but also what particular credential type issuer or verifier is authorized for.

Development & Operations

The service will be provided as Docker image, deployed and operated by Governing Authority (Bankserve). Regarding the development, DIDx company has already implemented trust registry as part of their bigger SSI solution. One option is to extract that and continue the development there. It's written in Python. At Absa, we can provide some resources or lead the development, but we use mainly Node.js.

Could be the solution distributed for reading? That would mean that other participant can keep their own version cached and just getting notification about changes. (Lohan: Is this what you meant by more distributed system?)

Only the Govenring Authority will have rights to add/remove entities and assign credential types to them. Any given entity could eventually do updates about itself, signed by its DID. This might require that supporting functionality for singing is implemented on the issuer/verifier side.

Future Enhancements

  • Verification policies for verifiers to simplify the creation of presentation request to fulfill particular business process
  • Offline support
  • Backward compatibility when someone/something is removed/updated/outdated
  • JSON-LD sign/verify
  • secondary trust registries
  • authorized holder wallets
  • use OCA for branding (logo, colors) and icons instead of trust registry

Resources

Alternative Solutions

DIF Trust Establishment

See https://identity.foundation/trust-establishment/.

The structure of the list of trusted issuers:

{
  "$id": "https://example.com/trusted-issuers-for-credential.schema.json",
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "title": "Trusted Issuers for Credential",
  "type": "object",
  "properties": {
    "credential": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "minItems": 1
    }
  },
  "required": ["credential"],
  "additionalProperties": false
}

The list of trusted issuers itself:

{
  "id": "32f54163-7166-48f1-93d8-ff217bdb0653",
  "author": "did:example:alice",
  "created": "2010-01-01T19:23:24Z",
  "validFrom": "2010-01-01T19:23:24Z",
  "version": "0.0.1",
  "entries": {
    "https://example.com/trusted-issuers-for-credential.schema.json": {
      "did:example:bob": {
        "credentials": ["example.com/dank-meme.schema.json", "example.com/danker-meme.schema.json"]
      },
      "did:example:carol": {
        "credentials": ["example.com/dankest-meme.schema.json", "example.com/dankest-meme.schema.json.ld"]
      }
    }
  }
}

Trinsic Demo

See What Is a Trust Registry? (Demo of Trinsic's Trust Registry Service).

Link to trust registry from issuer field in JSON-LD credential

{
  "IssuerIsSigner": {
    "is_valid": true,
    "messages": []
  },
  "TrustRegistryMembership": {
    "is_valid": true,
    "messages": []
  }
}
Select a repo