12

I started following a tutorial that wasn't cased around Android and got this:

    System.setProperty("javax.net.ssl.trustStore", "truststore");
    System.setProperty("javax.net.ssl.trustStorePassword", "password");

    SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    try {
        Socket s = ssf.createSocket("192.168.2.11", 6543);
        PrintWriter out = new PrintWriter(s.getOutputStream());
        while (true){
            out.println("SSL TEST");
            Log.d("DATA", "DATA SENT");
        }



    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

I guess this boils down to a few questions:

  1. I do not have my own trust store created, but searching through tutorials and things online, I am not sure how to create one. Is there a way I can create or modify a trust store to have the certificates I need in it? (I am using a self-signed certificate if that makes any difference)

  2. How do I make things with the SSL handshake run smoothly? Right now, the error I am getting is:

    javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    

    Honestly, I don't really understand what that means.

  3. What settings or files do I need to modify on my Android device to make sure this connection can happen?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Matt
  • 5,404
  • 3
  • 27
  • 39
  • You should probably just start with the Android way to do it, rather than try to modify a non-Android technique. – Matt Ball Jun 22 '11 at 14:13
  • I also tried placing the keystore file I have from my server and placing that in my jdk/jre/lib/security folder and then changing the trust store location and password to match that and I got the same Exception. – Matt Jun 22 '11 at 14:14
  • WAIT! what is "the Android way to do it" ? – Matt Jun 22 '11 at 14:15
  • If I yell loudly for help, does that mean people will answer my question more quickly? Also, my current approach is trying to get an SSLSocketFactory from an SSLContext which I am trying to initialize with my keystore. Still working out the kinks here, but it might be promising. – Matt Jun 22 '11 at 15:47

2 Answers2

11

1) It depends. Do you have a self signed cert on the server side and you are trying to validate your identity to the android device? Or are you on the android side trying to validate your idendity to the server? If it is the former , then please see this link: http://www.codeproject.com/KB/android/SSLVerification_Android.aspx?display=Mobile

You want to pay particular attention to where it makes the KeyStore file.

2) The reason you're getting that error is because it doesn't trust the server you are connecting either because you did not create the truststore correctly or you are connecting to a server whose certificate has not been added to the truststore. What exactly are you trying to connect to?

3) Make sure you have the <uses-permission android:name="android.permission.INTERNET" /> in the manifest.xml.

Edit My apologies, please see the changes I made to the first paragraph.

Here is the part to initialize your keystore and truststore

SSLcontext sslContext = SSLContext.getDefault();

KeyStore trustSt = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = this.getResources().openRawResource(R.raw.truststore);
trustSt.load(trustStoreStream, "<yourpassword>".toCharArray());
trustManagerFactory.init(trustStre);

KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = this.getResources().openRawResource(R.raw.keystore);
keyStore.load(keyStoreStream, "<yourpassword>".toCharArray());
keyManagerFactory.init(keyStore, "<yourpassword>".toCharArray());

sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
Otra
  • 8,108
  • 3
  • 34
  • 49
  • [+1] 1) I will investigate that, though (before looking at this website) I am not sure I understand the distinction between keystore and truststore. 2)I probably didn't create the trust store correctly... I used the keytool feature in the JRE 3) Looks like I at least got this part correct :0) – Matt Jun 22 '11 at 14:18
  • 1
    Hi, sorry, I made a mistake in the first paragraph, please see the changes. – Otra Jun 22 '11 at 14:24
  • 2
    The way I think of the difference between trust store and keystore is the trust store is the list of certificates that I trust, so if I'm on the android side, I want to have the server cert in my trust store. The keystore is where I keep my credentials to validate to the server. On the serverside, the trust store is where I keep a list of the clients I trust and the keystore is where I keep my own credentials. – Otra Jun 22 '11 at 14:26
  • I have a self-signed cert on the server side. I investigated the link, though I am not sure how to make an SSLFactory that uses my keystore. – Matt Jun 22 '11 at 14:57
  • 1
    Are you doing client auth as well? (does the android device need a cert?) Once I know this, I can edit my response with some code. – Otra Jun 22 '11 at 14:59
  • Sorry, I have been trying things that I thought might work... they didn't. I believe I am doing client auth as well. I am fairly certain the Android needs a cert. – Matt Jun 22 '11 at 15:25
  • Well... On second thought, the android probably only needs to trust the existing cert on the server. I don't know if that means it needs a cert or not. I apologize for my lack of knowledge here. – Matt Jun 22 '11 at 15:27
  • This looks a lot like what I have except that I don't have the keyManagerFactory. Any chance I could get a rough explanation of what that does? – Matt Jun 22 '11 at 17:57
  • 1
    *sigh* this didn't fix it, I still get the same exception detailed in my original post. So what now? – Matt Jun 22 '11 at 18:07
1

You don't need your own truststore unless the peer is using self-signed certifictes. The JRE ships with a truststore that is used by default, which trusts certificates issued by all the major CAs.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • @Matt so you need to create a truststore. Copy the one from the JDK; export the server certificate into a file; and import it into the new truststore. – user207421 Jun 25 '11 at 10:07