RSAKey.parse(rsaKey.toJSONObject()) fails when it contains an "x5c" attribute

Issue #314 resolved
D Laurent created an issue

RSAKey.parse(rsaKey.toJSONObject()) fails when it contains an "x5c" attribute

The stack is

java.text.ParseException: Unexpected type of JSON object member with key "x5c"

at com.nimbusds.jose.util.JSONObjectUtils.getGeneric(JSONObjectUtils.java:127)
at com.nimbusds.jose.util.JSONObjectUtils.getJSONArray(JSONObjectUtils.java:313)
at com.nimbusds.jose.jwk.JWKMetadata.parseX509CertChain(JWKMetadata.java:217)
at com.nimbusds.jose.jwk.RSAKey.parse(RSAKey.java:2133)

A simple reproducer:

    @Test
    public void testRSAKeyRoundtripWithX5c() throws Exception {

        RSAKey rsaKey = RSAKey.parse(
                "{\"kty\":\"RSA\",\"x5t#S256\":\"QOjjUwPhfMBMIT2zn5nrUxc4GocujsSHziKh-FlvmiU\",\"e\":\"AQAB\",\"kid\":\"18031265869169735523\",\"x5c\":[\"MIIDljCCAn4CCQD6O+zGNny3YzANBgkqhkiG9w0BAQsFADCBpTELMAkGA1UEBhMCQkUxEDAOBgNVBAgTB0JlbGdpdW0xETAPBgNVBAcTCEJydXNzZWxzMRwwGgYDVQQKExNFdXJvcGVhbiBDb21taXNzaW9uMRAwDgYDVQQLEwdTRkMyMDE0MR8wHQYDVQQDExZTRkMyMDE0IENBIERFVkVMT1BNRU5UMSAwHgYJKoZIhvcNAQkBFhF2YW53b2JlQHlhaG9vLkNvbTAeFw0xNjEwMTgxNTE4NTdaFw0yNjEwMTYxNTE4NTdaMHQxCzAJBgNVBAYTAkJFMRAwDgYDVQQIEwdCRUxHSVVNMREwDwYDVQQHEwhCcnVzc2VsczEcMBoGA1UEChMTRXVyb3BlYW4gQ29tbWlzc2lvbjEQMA4GA1UECxMHU0ZDMjAxNDEQMA4GA1UEAxMHdmFud29iZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMC7n95a0Yp\\/anE2ya3VhUjJ8KhoC8mAiblGJYMPsB2QfLKJEoZ2eSCD\\/GwkxufEb8UPauQDFogMshUZwwZ08k0OXywh3a9xO9zI+CCz23TNvueACQzWbtwWrx6lU5ljOOhBdt+c\\/CRXXgG2kH+hhs8MaV5KgN6iPf0HilH3QP2pwLNVLrupm\\/0r9CwuEc\\/wWLbi1nLno366vn\\/+jdsuxSrWnr\\/S8SCY3+L6CzZfhWMzF1SrsiCn+v6MirAwcG2IckNomGiL+X7PjObOSIWDVa7G9\\/Ouh4EaZN0w\\/zUvMSZ8mXkTo\\/Qk48kQlzm\\/KoQpEcoa9Dng4EdGyXzsipxsCNsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAlBtx8Lh3PL1PBoiki5VkPUqfNlYNE6C+3faPzjEKu0D8+g\\/y1AbFp7442J3QqX0yfS\\/qG3BIc2dU8ICDhmstn7d2yr+FDFF4raQ8OfMocQy66Rf6wgAQy0YETWF+gBx8bKhd3D+V12paZg8ocDE7+V0UOCmxRMSz8hRvycCYGlf5pD2v2DIfPatNgwyASZK+qu+w++OrilC3wXKG2XD8AWaoTWMWz1ycov6pSnRGEr0DNxF4DBWrJWe\\/b+HH1K1hiKG0lnD520Ldoy3VRF86uRBnAjKX0yy7LHZy1QaB6M5DHtzOQFg7GldjhuZVFA01smyadepiOI0jc6jTwghT2Q==\"],\"n\":\"wLuf3lrRin9qcTbJrdWFSMnwqGgLyYCJuUYlgw-wHZB8sokShnZ5IIP8bCTG58RvxQ9q5AMWiAyyFRnDBnTyTQ5fLCHdr3E73Mj4ILPbdM2-54AJDNZu3BavHqVTmWM46EF235z8JFdeAbaQf6GGzwxpXkqA3qI9_QeKUfdA_anAs1Uuu6mb_Sv0LC4Rz_BYtuLWcuejfrq-f_6N2y7FKtaev9LxIJjf4voLNl-FYzMXVKuyIKf6_oyKsDBwbYhyQ2iYaIv5fs-M5s5IhYNVrsb3866HgRpk3TD_NS8xJnyZeROj9CTjyRCXOb8qhCkRyhr0OeDgR0bJfOyKnGwI2w\"}");

        // Fails with java.text.ParseException: Unexpected type of JSON object member with key "x5c"
        RSAKey secondPassKey = RSAKey.parse(rsaKey.toJSONObject());

        assertThat(secondPassKey, is(rsaKey));
    }

The reason behind the exception lies in com.nimbusds.jose.jwk.JWK#toJSONObject where the x5c field is put into the jsonObject as-is:

        if (x5c != null) {
            o.put("x5c", x5c);
        }

and the x5c field is

    /**
     * The X.509 certificate chain, optional.
     */
    private final List<Base64> x5c;

In RSAKey the x5c field will be a Collections.unmodifiableList in front of a LinkedList.

The exception occurs in com.nimbusds.jose.util.JSONObjectUtils#getGeneric

in

        if (! clazz.isAssignableFrom(value.getClass())) {
            throw new ParseException("Unexpected type of JSON object member with key \"" + key + "\"", 0);
        }

because the Collections.UnmodifiableList is not assignable from the JSONArray.class

A potential fix would be to convert the x5c List into a JSONArray in com.nimbusds.jose.jwk.JWK#toJSONObject (i.e. when it is not assignable from JSONArray already).

Comments (4)

  1. Log in to comment