Generic issuance in NL Wallet ecosystem

The NL Wallet uses SD-JWT VC Type Metadata documents for validating both SD-JWT and ISO mdoc formatted attestations. The following paragraphs describe how this works.

SD-JWT

The SD-JWT VC Type Metadata is applied to SD-JWT formatted attestations as described in the SD-JWT VC specification.

mdoc

For mdoc, no formal metadata specification exists. Instead of developing a custom metadata scheme for mdoc attestations, the NL Wallet uses the SD-JWT VC Type Metadata with some adaptations to describe the contents of an mdoc formatted attestation.

The relevant differences between mdocs and SD-JWT formatted attestations are:

  1. Mdoc documents use the CBOR serialization format, whereas SD-JWT documents use JSON.

  2. Contrary to SD-JWT, in mdocs arbitrarily deep nesting of claims is not supported: In mdocs, the attribute values are put in attribute groups called the “namespace”. In other words, mdocs always have a nesting of exactly one level deep.

The remainder of this document explains how the NL Wallet deals with these differences.

1. Serialize the mdoc to JSON for JSON Schema

SD-JWT VC Type Metadata documents may contain a JSON Schema document to enable verifying the structure and format of the attestation and the attributes within it, ensuring that the attestatation has certain fields and attributes of certain JSON data types. After deserializing the CBOR-formatted attestation, the NL Wallet serializes it to JSON as described in Section 6.1 of the CBOR specification to enable validating it against the JSON Schema contained in the SD-JWT VC Type Metadata document.

2. Convert namespace structure to nested SD-JWT structure

Before verifying the mdoc against the SD-JWT VC Type Metadata, the mdoc needs to be transformed to mimic the structure that an SD-JWT formatted attestation based on the same Type Metadata would have. This is done using the path array in the claims objects in the Type Metadata (see the example below). Iterating over the attributes in the claims object in the Type Metadata, for each attribute:

  • The final element of the path array is the attribute name.

  • The mdoc namespace is computed by (1) concatenating the remaining elements of the path array with a dot . and (2) prefixing that with the attestation type.

  • Given this namespace and attribute name, lookup the attribute value in the mdoc.

  • Use the path array to construct the location of the attribute inside the nested JSON structure, and place the attribute value there.

Example

SD-JWT VC Type Metadata used for validation

In the example below, the following SD-JWT VC Type Metadata is used.

{
  "vct": "com.example.address",
  // ... display data of the attestation here
  "claims": [
    {
      "path": [ "city" ],
      "display": [ /* ... */ ],
      "sd": "always"
    },
    {
      "path": [ "street" ],
      "display": [ /* ... */ ],
      "sd": "always"
    },
    {
      "path": [ "house", "number" ],
      "display": [ /* ... */ ],
      "sd": "always"
    },
    {
      "path": [ "house", "letter" ],
      "display": [ /* ... */ ],
      "sd": "always"
    }
  ],
  "schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "vct":           { "type": "string" },
      "vct#integrity": { "type": "string" },
      "city":          { "type": "string" },
      "street":        { "type": "string" },
      "house": {
        "type": "object",
        "properties": {
          "number":    { "type": "number" },
          "letter":    { "type": "string"}
        },
        "minProperties": 1
      }
    },
    "required": [ "vct", "vct#integrity", "cnf", "iat", "exp", "city", "street", "house" ]
  }
}

Mdoc formatted document snippet

Suppose that the mdoc looks as follows. In this JSON snippet, the object keys in the root object denote the mdoc namespaces and the elements under those are the attributes.

// doctype/vct is "com.example.address"
{
    "com.example.address": {
        "city": "The Capital",
        "street": "Main St."
    },
    "com.example.address.house": {
        "number": 1,
        "letter": "A"
    }
} 

Transformed snippet used for validation against Type Metadata

The JSON structure is constructed using the claims paths in the Type Metadata (see above). This results in the following reconstructed SD-JWT claimset.

// doctype/vct is "com.example.address"
{
  "city": "The Capital",
  "street": "Main St.",
  "house": {
      "number": 1, 
      "letter": "A"
   }
}