0

I'm using Netty on Android and server side to establish a SSL-secured connection with client-authentication. Now I'm having difficulties connecting with these certificates since SSLEngine declines them due to "null cert chain".

This is what I've done on the Server side. I set up an SSLContext with a signed Server Certificat (the client knows the CA so it can validate this one).

To make the server accept any certificates from clients (since they are all self-signed) I implemented an DummyTrustManager that will just accept any.

private static class DummyTrustManager implements X509TrustManager
    {
        private X509Certificate[] mCerts;

        public DummyTrustManager(Certificate[] pCerts)
        {
            // convert into x509 array
            mCerts = new X509Certificate[pCerts.length];
            for(int i = 0; i < pCerts.length; i++)
            {
                mCerts[i] = (X509Certificate)pCerts[i];
            }
        }

        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}

        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{}

        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return mCerts;
            //return new X509Certificate[0];
        }
    }

The point is that I'm not quite sure about the getAcceptedIssuers() method.

  • If I retrurn an empty array than the openssl-binary (which I use to veryfi the correct setup) fails due to an empty AcceptedIssuers list.

  • If I add the currents server certificate chain than it will work at least for client certificates that were signed by the same ca but not with ones that are self signed (which is what I need).

But maybe I'm doing something wrong on the client side:

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);

        keyStore.setEntry("user_certificate", new KeyStore.PrivateKeyEntry(mPrivate, new Certificate[]{mClientCert}), this);
        keyStore.setCertificateEntry("server_certificate", mServerCert);

Also I did some researches and from what I understood so far: The client has a valid certificate chain but does not send it because the server tells it that it only accepts the issuers listed by the server.

If this is right, then how can I overcome this issue?

I was thinking of an seperate self-signed CA that is delivered to all clients and that is also listed in the server accepted issuers list. Any client uses this CA to sign its own certificate. I see of no security problem with this. Or is there a better solution?

Chris
  • 661
  • 2
  • 7
  • 23
  • Something wrong here. Using client authentication and accepting any client certificate are mutually contradictory. Why use client authentication at all if you don't care who the clients are, or whether they have valid certificates? NB you don't need OpenSSL: Java is packed full of crypto APIs. – user207421 May 14 '13 at 18:08
  • 1
    I'm using the client certificate as a login token. Unknown certificates will be threaded as new clients and registered. So there is a reason for having both. And sadly Java does not have a full crypto packet. I even have to use Bouncycastle just to create self signed certificates on client side. I used openssl only because of its s_client parameter which allows you to check if your SSL handshake is working fine. – Chris May 14 '13 at 21:59

1 Answers1

1

Since there was no answer for a longer period I'm going to give a brief overview of how I will solve this for now.

I've created another CA that is not signed by any trusted CA. Actually it is self signed. This CA is given to all clients to sign their own certificates. Why? Because that way I can tell the server to send out this CA as the only accepted one getAcceptedIssuers(). This is not intended to give a level of authority. The way I check the clients is only by their public key, so there is no security risk there.

You only have to be very carefull to not mix your TrustedManagers and SSLContext instances up.

Chris
  • 661
  • 2
  • 7
  • 23
  • The security risk is that the CA will leak from one of your clients to someone who hasn't paid, or whatever it is you're trying to protect yourself from. You've really accomplished very little here. – user207421 May 23 '13 at 00:49
  • 1
    As mentioned earlier. I'm not using SSL in the way most people do. I need to establish a connection where the client is using a public key instead of an username/password. I could even except every issuer since I check any client by its public key and **not** by the issuer. The public CA is only a way to trick (that I would like to skip if I can, which is what my question was about) Java because otherwise the client side does not send any certificate at all. Any public key that I don't know is threaded as new and can register itself on my server. – Chris May 23 '13 at 00:53