Skip to content

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

@edgar-bit

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions