SSLHandshakeException on connection

I’m trying to implement Smack 4.1 in my android app to communicate witch my ejabberd server, during the connection i get the following exception

10-24 16:30:55.479 21033-21070/com.demo.xmppchat D/dalvikvm﹕ GC_FOR_ALLOC freed 370K, 3% free 17153K/17556K, paused 10ms, total 10ms

10-24 16:30:55.489 21033-21070/com.demo.xmppchat D/SMACK﹕ SENT (0): <stream:stream xmlns=‘jabber:client’ to=‘178.62.199.13’ xmlns:stream=‘http://etherx.jabber.org/streams’ version=‘1.0’>

10-24 16:30:55.559 21033-21071/com.demo.xmppchat D/SMACK﹕ RCV (0): <?xml version='1.0'?><stream:stream xmlns=‘jabber:client’ xmlns:stream=‘http://etherx.jabber.org/streams’ id=‘3386981479’ from=‘178.62.199.13’ version=‘1.0’ xml:lang=‘en’>stream:featuresSCRAM-SHA-1DIGEST-MD5PLAIN<register xmlns='http://jabber.org/features/iq-register’/></stream:features>

10-24 16:30:55.559 21033-21070/com.demo.xmppchat D/SMACK﹕ SENT (0):

10-24 16:30:55.629 21033-21071/com.demo.xmppchat D/SMACK﹕ RCV (0):

10-24 16:30:55.769 21033-21071/com.demo.xmppchat W/AbstractXMPPConnection﹕ Connection closed with error

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

at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.ja va:409)

at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.(OpenSSLSocket Impl.java:661)

at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.ja va:632)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnect ion.java:661)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnecti on.java:768)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1000(XMPPTCPConnection.java :132)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPC onnection.java:1068)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPCon nection.java:969)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnecti on.java:988)

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:2 82)

at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl. java:202)

at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocke tImpl.java:611)

at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)

at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.ja va:405)

at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.(OpenSSLSocket Impl.java:661)

at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.ja va:632)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnect ion.java:661)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnecti on.java:768)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1000(XMPPTCPConnection.java :132)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPC onnection.java:1068)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPCon nection.java:969)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnecti on.java:988)

Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:2 82)

at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl. java:202)

at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocke tImpl.java:611)

at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)

at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.ja va:405)

at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.(OpenSSLSocket Impl.java:661)

at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.ja va:632)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnect ion.java:661)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnecti on.java:768)

at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1000(XMPPTCPConnection.java :132)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPC onnection.java:1068)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPCon nection.java:969)

at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnecti on.java:988)

10-24 16:30:55.769 21033-21071/com.demo.xmppchat D/Connection﹕ Closed On error

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.ja va:409)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.(OpenSSLSocket Impl.java:661)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.ja va:632)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.initReaderAndWriter(XMPPTCPConnect ion.java:661)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.proceedTLSReceived(XMPPTCPConnecti on.java:768)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1000(XMPPTCPConnection.java :132)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPC onnection.java:1068)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPCon nection.java:969)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnecti on.java:988)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:2 82)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl. java:202)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocke tImpl.java:611)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.ja va:405)

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ … 8 more

10-24 16:30:55.779 21033-21071/com.demo.xmppchat W/System.err﹕ Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Could somebody help me?

I’ve recently seen something similar recently while opening an https connection to a server on an older device. The necessary certificates weren’t in the collection of ‘trusted’ certificates.

Verify that the root certificate of the server that you are attempting to connect with is one of the CA’s found in your device’s settings under “Settings–>Security–>Trusted credentials”

If you are using your own self-signed certificate, you may need to include it explicitly in your android build.

Not sure if this helps, here’s how I got around the “no trusted root” problem…

I’m adding specifically adding an entire certificate chain as my ONLY trusted certificates (no possible man-in-the-middle).

I’m using the ‘spongycastle’ library and inserting it ahead of the regular (possibly outdated) security providers on the device:

Add to Gradle:

compile 'com.madgag.spongycastle:core:1.51.0.0’
compile 'com.madgag.spongycastle:prov:1.51.0.0’
compile ‘com.madgag.spongycastle:pkix:1.51.0.0’

Load the SpongyCastle package as the ‘default’ security implementation:

This should occur before you create the SSLContext or any other security operations.

The logging statement should show you all the others too…

/**

  • Explicitly specify the usage of the SpongyCastle library in preference to the library that’s
  • included with Android. Many devices do not include complete implementations of the BouncyCastle
  • API, and are flawed in that they cannot be easily updated when new vulnerabilities are exposed.
  • The SpongyCastle implementation takes the source code from the BouncyCastle project, and simply renames
  • the packages to avoid any confusion on the part of Android’s classloader. SpongyCastle uses the same
  • MIT X11 license as BouncyCastle, and can obtained online for inspection.

*/
static {

Provider[] providers = Security.getProviders();
if (null == providers || !“SC”.equals(providers[0].getName())) {

Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
}

if (true) {

providers = Security.getProviders();
for (int inx = 0; inx < providers.length; inx++) {

Log.d(TAG, MessageFormat.format(“Security Provider[{0}] = {1}”, inx, providers[inx].getName()));
}

}

}

Then I make sure that the SSLSocketFactory uses a security context with Spongy Castle as the provider…

/**

  • Creates a custom SSLContext that has ONLY the known good keys.
  • @return An SSLContext that knows the provided keys and doesn’t provide client authentication
  • @throws GeneralSecurityException
  • @throws IOException
    */
    public SSLContext createSslContext() throws GeneralSecurityException, IOException {

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

// Specify the ‘SpongyCastle’ provider explicitly, may be overkill but safe
KeyStore trustedKeys = KeyStore.getInstance(KeyStore.getDefaultType(), “SC”);
trustedKeys.load(null, null); // Initialize the empty keystore
trustManagerFactory.init(trustedKeys);

// Insert the trusted certificates by name
List knownCertificates = new ArrayList<>();
CertificateUtils.getCertificateChain(context, knownCertificates);
for (X509Certificate c : knownCertificates) {

trustedKeys.setCertificateEntry(c.getSubjectDN().getName(), c);
}

// Wrap it up in an SSL context, no private keys, but yes for foreign certificates.
SSLContext sslContext = SSLContext.getInstance(“TLS”);
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext;
}

The X509 Certificates for the server are loaded up by reading them from the ‘raw’ resources:

/**

  • Reads the ‘src.cer’ Certificate bundled with the application. The resulting
  • X509 style certificate can be further parsed for dates, threshold and bundled weightings.
  • @param context Android Context permitting and defining access to system resources
  • @param filename Regular text file containing the encoded certificate information
  • @return An X509Certificate object read from the specified file
  • @throws CertificateException In the event that the file cannot be properly parsed or the certificate
  • cannot be constructed from the file.
  • @throws IOException In the event that the file doesn’t exist and/or cannot be read.
    */
    public static X509Certificate readX509Asset(Context context, String filename) throws CertificateException, IOException {

X509Certificate xCert = null;
try {

CertificateFactory cf = CertificateFactory.getInstance(“X.509”);

InputStream rawInput = context.getAssets().open(filename);
InputStream caInput = new BufferedInputStream(rawInput);

Certificate certificate = cf.generateCertificate(caInput);
caInput.close();
rawInput.close();

if (certificate instanceof X509Certificate) {

xCert = (X509Certificate) certificate;
}

} catch (IOException ioe) {

Log.e(TAG, “File Problem”, ioe);
throw ioe;
}

return xCert;
}

Hope this helps…