Skip to content

Recursive array objects other than leaf elements not correctly decoded #8

Description

@edgar-bit

Description

There is a tiny problem with the decoding of recursive array elements => Resolving of other nested maps or list does not work => leaf elements work perfectly.

Steps to Reproduce

With an sdjwt-payload similar to:

{
  "object": {
    "array_arrays": [
      1,
      3.14,
      "string",
      [0],
      [1],
      [2],
      {
        "claim": "Nested element",
        "other": {
          "deeply": "nested"
        }
      }
    ]
  }
}

Then encode it recursively. An example credential could look like:

eyJ0eXAiOiJ2YytzZC1qd3QiLCJhbGciOiJFUzI1NiJ9.eyJpc3MiOiJkaWQ6ZXhhbXBsZTppc3N1ZXIiLCJfc2QiOlsiTWtuTi0zVWtJem9ka3RfeGZKVDd4VTQ2QjhoTGdleE1oNWZlQlNjRE1aTSJdLCJpYXQiOjE3Nzc1MDcyMDAsInZjdCI6InVybjp2Y3Q6dGVzdDoxIiwiX3NkX2FsZyI6InNoYS0yNTYifQ.Uo8LYu84xjxG6Z9rjcV8LMdhnE-JUEg_y3vwBjblhgcqfGJ_enXMUmzn0aYeuttYlgSFs3ruxkhdWoWLMlZYyw~WyJFdENBa3ZOdjF2OS01cUpCSFZkTXZ3IiwxXQ~WyJqMVN4RGNlVXk0Vmx2VzFJSVlTdjlRIiwzLjE0XQ~WyJYalBtVUJjV0REa3JFNGpya1B1Z3RBIiwic3RyaW5nIl0~WyJSQXlZYXVia203Z2pxWmFVbmRfaE5nIiwwXQ~WyI4bEpWWXRMT2ZpR00wOEpocnAwZ0p3IixbeyIuLi4iOiJCUGpvaWdNUlhVbDV2eTBLZ2VEVGdFamZDUkhOVHVueDNtREdaOWtpWVhNIn1dXQ~WyJZM3J5T2JRNHVLS3QtX2szLTdITG9RIiwxXQ~WyJhTmU2R2UwTi0zNExPMS1JbGQzWGlRIixbeyIuLi4iOiJFVnBscmlhRWhqM3hyZkdhSW1sNE1ERWpJTGNkNVVOQVZudUU5TUVOM2FRIn1dXQ~WyJBSG1yNFd0R2RhbVA0SjVoRVlmdXF3IiwyXQ~WyI1TVJYTW9NN0VnQzJRa0t2ei1NaE53IixbeyIuLi4iOiI0Z0NlTGJwVFdEdjNUZ0xNYTVfZzkxSkVFN09hSlZ0WWRzclV0Yk5JaFI4In1dXQ~WyJ5NGwtVndoREtYbTRod3FsajY1MDN3IiwiY2xhaW0iLCJOZXN0ZWQgZWxlbWVudCJd~WyJndjBGNFdPamtqLUlkdjY1d0k5V2VnIiwiZGVlcGx5IiwibmVzdGVkIl0~WyJFbUpJbHZvaTdxUlI4U3pnMk9Lci1nIiwib3RoZXIiLHsiX3NkIjpbInZwMmhvYzROeGhuOUM2aXRaMDdMSl9CWEdMUC1CVnp3WmdsQWtmTEcwWXciXX1d~WyJFUGQ5ZVIwa2lOS21pSmFxTXdlc0RnIix7Il9zZCI6WyJKbXZ6M29aMWxPZHdjNXQ1cGFFaTE3SjdXLU0yOElEUzVQRUJSd2hudFpBIiwid3FYaklGLTJhZEdyYXhKSHRKa1ZERTVYVmNCRVRaRU94LW5fTGNQUmFPVSJdfV0~WyJtNkFicUZiYUdnM1N3MUJtc2phVkNBIiwiYXJyYXlfYXJyYXlzIixbeyIuLi4iOiJTM0FILW1PQXU0T2traVp5dTNSeThYS05JWm5LVGR0dGkwRklqMUlHVWNRIn0seyIuLi4iOiJsc1dPbl9WdVpwSUJjejZscXhNZWMwbTdnemtoNXVlZWxZVEdMb3NsTVdNIn0seyIuLi4iOiJ6elNuaWxXWEZtMzh1eGFzcmdzeDUycUZZZk1HR2VCcWJkc0gzaTg3ZElVIn0seyIuLi4iOiJ1ZEZrQUZ1bUMtSXJUNVY3dmFibUlpeFpXaTNFOFNYYTQ2RkkzR003bTZrIn0seyIuLi4iOiJpTDNQdkZISUZxN1R3RGRDMzByM2JMNXJEenhLc3dGRFVmYVJuMjJycHVBIn0seyIuLi4iOiJRQTBUU0N5c3dMeDc0UzY5QWUzdno4TUVvTm1wa3JzUWRHR1FGUGM2RDZZIn0seyIuLi4iOiJnaTNfRFZ2QVpBdHB2Q24zOWR4d1BVV1ljT2VCS1dvcGU2SklENmJ6VzFvIn1dXQ~WyJIMmF0aXZ2cmctUng3bEkzUVpXa0VRIiwib2JqZWN0Iix7Il9zZCI6WyJzcmJtZ254MkluNW5uRC1BS2V4SWZDTVNqVmljYXh6ZFcyQy1GRmpfVVRVIl19XQ~

And decode it again with:

var decoded = decode(signedJWT.getJWTClaimsSet().toJSONObject(), disclosures);
var decodedMap = decoder.decode(signedJWT.getJWTClaimsSet().toJSONObject(), disclosures);

The decoded map looks like:

{
  "object" : {
    "array_arrays" : [ 1.0, 3.14, "string", [ {
      "..." : "BPjoigMRXUl5vy0KgeDTgEjfCRHNTunx3mDGZ9kiYXM"
    } ], [ {
      "..." : "EVplriaEhj3xrfGaIml4MDEjILcd5UNAVnuE9MEN3aQ"
    } ], [ {
      "..." : "4gCeLbpTWDv3TgLMa5_g91JEE7OaJVtYdsrUtbNIhR8"
    } ], {
      "_sd" : [ "Jmvz3oZ1lOdwc5t5paEi17J7W-M28IDS5PEBRwhntZA", "wqXjIF-2adGraxJHtJkVDE5XVcBETZEOx-n_LcPRaOU" ]
    } ]
  },
  "vct" : "urn:vct:test:1",
  "iss" : "did:example:issuer",
  "iat" : 1777507200
}

So the decoding is not complete.

Expected Behavior

The decoded map and the encoded map are the same

Possible fix

In order to fix this behaviour sth. like:

private void decodeDots(
            Map<String, Disclosure> digestMap,
            String digest, List<Object> decodedList) {
        // Get a disclosure that corresponds to the digest.
        Disclosure disclosure = digestMap.get(digest);

        // If the disclosure that corresponds to the digest is not found.
        if (disclosure == null) {
            // There are two possibilities.
            //
            //   1. The array element corresponding to the digest is not disclosed.
            //   2. The digest is a decoy digest.
            //
            // In either case, no element is added to the decoded list.
            return;
        }

        // If the disclosure has a claim name.
        if (disclosure.getClaimName() != null) {
            // That the claim name of a disclosure is not null means that the
            // disclosure is for an object property, not for an array element.
            throw new IllegalArgumentException(
                    "The digest of a disclosure for an object property is specified by '...'.");
        }

        // Add the disclosed array element.
        // Change here:
        switch (disclosure.getClaimValue()) {
            case Map<?, ?> m -> decodedList.add(decodeMap(digestMap, (Map<String, Object>) m));
            case List<?> l -> decodedList.add(decodeList(digestMap, l));
            default -> decodedList.add(disclosure.getClaimValue());
        }
    }

could fix the problem

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions