Scottie9811 Scottie9811 - 5 months ago 86
Android Question

How to add a certificate to the Android trust store?

I got a client app designed for Android. Android apps are based around XML and Java, well so is our server side app for Windows. The issue is that since we are working with Android now, we have to deal with the trust store. Is there any way to add a certificate to the trust store dynamically?

Client side connection code:

InputStream stream = main.getResources().openRawResource(R.raw.keystore);
KeyStore trustStore;
try {
trustStore = KeyStore.getInstance("BKS");
trustStore.load(stream, password.toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
try{
clientSocket = (SSLSocket) factory.createSocket(simpleAddress, simplePort);
}catch (Exception ex){
ex.printStackTrace();
}


Server side connection code:

System.setProperty("javax.net.ssl.keyStore", System.getProperty("java.io.tmpdir") + "keystore_30290.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
try {
server = ((SSLServerSocket)factory.createServerSocket(config.port));
} catch (Exception e) {
e.printStackTrace();
System.out.println("[ERROR] Failed to bind ssl server socket to port "+config.port+".");
System.exit(-1);
}


Client side error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:629)
at com.android.org.conscrypt.OpenSSLSocketImpl.getOutputStream(OpenSSLSocketImpl.java:615)
at me.skorrloregaming.softlyirc.Internet.sendMessage(Internet.java:33)
at me.skorrloregaming.softlyirc.Internet.run(Internet.java:95)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:318)
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:219)
at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:556)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:324)
... 5 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
... 11 more
java.net.SocketException: Socket is closed
at com.android.org.conscrypt.OpenSSLSocketImpl.checkOpen(OpenSSLSocketImpl.java:247)
at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:573)
at me.skorrloregaming.softlyirc.Internet_Listen.run(Internet_Listen.java:20)
at java.lang.Thread.run(Thread.java:818)


Code for receiving information from server:

while (internet.running){
try{
if (internet.clientSocket.getInputStream().read() == -1) break;
byte[] messageBytes = new byte[internet.clientSocket.getInputStream().available()];
internet.clientSocket.getInputStream().read(messageBytes, 0, messageBytes.length);
String message = new String(messageBytes);
main.updateAdapter(message);
main.scrollUpdate();
}catch (Exception ex){
ex.printStackTrace();
break;
}
}
try{
internet.clientSocket.close();
}catch (Exception ex){
}
main.messageBox("Softly IRC", "End of stream (Connection Terminated)", new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
main.load(new Intent(main, Login.class));
}
});

Answer

Try something like this, given your trustStore:

TrustManagerFactory tmf=TrustManagerFactory
  .getInstance(TrustManagerFactory.getDefaultAlgorithm());

tmf.init(trustStore);

SSLContext sslContext=SSLContext.getInstance("TLSv1");

sslContext.init(null, tmf.getTrustManagers(), null);

SSLSocketFactory factory=sslContext.getSocketFactory();

// do something with that