1

I have a requirement where one can provide an intermediate CA to trust but not the CA(s) that have signed it. And using that as the trust store, I'd like to be able to trust an SSL server that has a certificate that's signed by this intermediate CA. The default implementation is to expect to build the whole chain until a trusted self-signed root CA is found. I believe that's how the whole X509 platform is based on. But for certain reasons, I can only provide the intermediate CA.

The code is the usual SSLContext creation:

    // keystore part is pseudocode to make a point
    KeyStore keyStore = someWayToGenerateKeyStore;
    keyStore.add(intermediateCa);
    //keyStore.add(rootCaThatSignedTheIntermediateCaAbove); it will work if I add this. But I don't want to for reasons.

    TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
    tmf.init(keyStore);
    SSLContext ctx = SSLContext.getInstance("TLSv1.2");
    ctx.init(new KeyManager[], tmf.getTrustManagers(), new SecureRandom());
    SslContextFactory sslContextFactory = new SslContextFactory();
    sslContextFactory.setSslContext(ctx);
    client = new WebSocketClient(sslContextFactory);

OpenSSL has a parameter for this that seems to work. So I guess it's not a completely unorthodox approach.

openssl verify -CApath /dev/null -partial_chain -trusted g1 g0

There are two reasons for the requirement to only have the intermediate CA in the truststore.

  • It makes it easier to pass around one trusted certificate around the system that currently depends on a single self-signed CA certificate. The communication and setup of many components expect a single certificate at the moment and changing that would require significant refactoring.
  • We want to make sure that we only trust the certificate signed by the given intermediate CA certificate. If we add the other CA certificates in the chain into the trust store, the SSL implementation will trust any certificate signed by the other CAs also which we want to avoid. There are probably other ways to do it like checking the issuer_dn but I'd like to explore different approaches.
Natan
  • 2,816
  • 20
  • 37

1 Answers1

0

The default implementation is to expect to build the whole chain until a trusted self-signed root CA is found

No it isn't. It is to verify the whole chain until a trusted signing certificate is found in your truststore. 'Self-signed' has nothing to do with it, and 'trusted ... root CA' means nothing more than that it is present in your truststore.

So all you need to do is to add that certificate to your truststore. You don't need to write any code at all.

But why you want to trust an intermediate signer without trusting the root signer is a mystery.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I'm sorry, I'm a bit confused about your answer because of the terms that might mean different things. Are you saying that it should work as long as I have the intermediate CA in the truststore but not the CA that signed that intermediate CA? That hasn't been my experience and that is not the behavior of OpenSSL unless one passes `-partial_chain` as parameter. I'll edit my question to explain the mystery. – Natan May 17 '18 at 11:38
  • 1. Your question is about Java, not OpenSSL. 2. You are making the all-too-common common mistake of conflating authentication with authorization. You should *trust* any certificate signed by a recognized CA, but whether you *authorize* the *identity* established by that certificate for your application is a completely different question. Certificate are for identity, not for authorization. – user207421 May 17 '18 at 12:30
  • 1. I did test Java counterpart and only adding intermediate CA to truststore does not work by default. Hence the question. If you're very confident that it should work, I'll debug more and look for other problems in my test. I have been using OpenSSL as a reinforcement argument since it's a very crucial implementation in x509 framework. 2. Noted. I appreciate the input. – Natan May 17 '18 at 16:19