Prevent accidental leakage of private key details from JWKs

Issue #22 resolved
Vladimir Dzhuvinov created an issue

The JPSK implementation that we have now incorporates the public and private parts in a single class. There is risk of leaking the private key details on public JWK serialisation with toJSONObject() - the developer loads the key pair but then forgets to make a JWK copy with the public params only.

Solution 1:

Add a toJSONObject(boolean includePrivate) method, then let the existing no arg method call toJSONObject(false).

JSONObject publicJWK = jwk.toJSONObject()

JSONObject privateJWK = jwk.toJSONObject(true);

Pros: A single object representation, with simple choice how to output JSON object with public only or public + private params.

Cons: The private / public property cannot be inferred from the class name; also, the full constructor allows for specifying incomplete private key representations.

Solution 2:

Extend public ECKey and public RSAKey with PrivateECKey and PrivateRSAKey.

Pros: Whether the key is public or private can be inferred from the class name.

Cons: Explicit type casting of PrivateECKey / PrivateRSAKey to ECKey / RSAKey required to serialise the public params with toJSONObject. The danger of the developer forgetting that can be mitigated by using the toJSONObject(boolean) method described in 1.

Solution 3:

Use the existing Java model: Base abstract ECKey, with extending PublicECKey and PrivateECKey classes. Similar for RSA key.

 java.security.interfaces.RSAKey
 java.security.interfaces.RSAPublicKey
 java.security.interfaces.RSAPrivateKey

Pros and cons: Same as with 2.

Comments (3)

  1. Vladimir Dzhuvinov reporter

    Solution 2 implemented in branch iss22, see commit 7476435 :

    ECPublicKey and RSAPublicKey store the public parameters.

    ECKeyPair and RSAKeyPair extend ECPublicKey and RSAPublicKey with private parameters.

    The existing toJSONObject() method of JWK and JWKSet will only include the public parameters in the output JSON, to prevent accidental leakage of sensitive key details. Added a second toJSONObject(boolean includeNonPublicParams) method that controls explicitly the inclusion of non-public params.

    Also moved all JWK-related classes to a separate package, to unclutter the base JOSE package and for greater clarity.

    The JavaDocs for this commit are at http://nimbusds.com/files/jose-jwt/javadoc/

  2. Justin Richer

    Alternate proposal to Solution 1 checked into branch native-keys:

    JWK defines new method toPublicJWK which returns a copy of the JWK with only the public keys defined. All serialization methods simply serialize the whole key object. Use would be:

    RSAKey key = ... // public and private keypair RSA JWK

    RSAKey pub = key.toPublicJWK();

    pub.toJSONString(); // serialize the public key

  3. Log in to comment