2

I understand this is something which is not so difficult but very unfortunately I am stuck here and fighting it since yesterday, I have followed this Mutual Authentication in Android tutorial, to place a keystore in resources and trying to connect to my server over SSL, but getting the following exception

java.lang.RuntimeException: org.spongycastle.jcajce.provider.asymmetric.x509.CertificateFactory$ExCertificateException

I have placed my sslapptruststore.pfx file under res/raw/sslapptruststore.pfx and using this piece of code

try {

                           KeyStore clientCert = KeyStore.getInstance("PKCS12");
                                   clientCert.load(getResources().openRawResource(R.raw.sslapptruststore), "123456".toCharArray());// this line causes exception

                            HttpClient httpClient = null;
                            HttpParams httpParams = new BasicHttpParams();
                            SSLSocketFactory sslSocketFactory = new SSLSocketFactory(clientCert, null, null);
                            SchemeRegistry registry = new SchemeRegistry();
                            registry.register(new Scheme("https", sslSocketFactory, 8443));
                            httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, registry), httpParams);


                            HttpPost httpPost = new HttpPost(
                                    "https://192.168.1.113:8443/CertProvider");
                            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
                            List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(2);
                            nameValuePair.add(new BasicNameValuePair("csr", csr.toString()));

                            // Url Encoding the POST parameters
                                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair));

                            // Making HTTP Request
                            // HttpResponse response = null;
                            ResponseHandler<String> responseHandler = new BasicResponseHandler();
                            String response = "";
                            response = httpClient.execute(httpPost, responseHandler);
                                } catch (Exception e) {
                                    Log.e("", e.getMessage());
                                }

I have also searched but others are using .bks.

Any help is appreciated.

SSH
  • 1,609
  • 2
  • 22
  • 42

2 Answers2

3

I have answered some questions look like your issue as the following:

Read in PKCS12/P12 Client Cert file for Android App

Android volley self signed HTTPS trust anchor for certification path not found

You will find

    private SSLSocketFactory getSSLSocketFactory_KeyStore(String keyStoreType, int keystoreResId, String keyPassword)
            throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {

        InputStream caInput = getResources().openRawResource(keystoreResId);

        // creating a KeyStore containing trusted CAs

        if (keyStoreType == null || keyStoreType.length() == 0) {
            keyStoreType = KeyStore.getDefaultType();
        }
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);

        keyStore.load(caInput, keyPassword.toCharArray());

        // creating a TrustManager that trusts the CAs in the KeyStore

        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, wrappedTrustManagers, null);

        return sslContext.getSocketFactory();
    }

and getSSLSocketFactory_Certificate for .cert file.

As in the first link above, in your project you can call one of the two methods:

If using keystore file:

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("PKCS12", R.raw.androidpkcs12, "123456789");

If using certificate file:

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("PKCS12", R.raw.androidpkcs12_cert);

P/S: If these methods are inside a non-activity class, to avoid NPE, you must pass Context from your Activity to that class (as inside the first link above).

Hope this helps!

Community
  • 1
  • 1
BNK
  • 23,994
  • 8
  • 77
  • 87
  • If not working, please tell me. Then, provide me with your .pfx file if possible so that I can check in my project :) – BNK Oct 07 '15 at 06:14
  • previuosly i put only signed certificate in the keystore, but i tried with a keystore having a complete chain, and it works and atleast able to load keystore but now am getting this exception << javax.net.ssl.SSLPeerUnverifiedException: No peer certificate >> – SSH Oct 07 '15 at 11:20
  • How were your keystore/cert files created? I use Keystore Explorer to create my files. – BNK Oct 07 '15 at 13:38
  • About exception "No peer...", IMO, you can read http://stackoverflow.com/questions/18126372/safely-fixing-javax-net-ssl-sslpeerunverifiedexception-no-peer-certificate. However, if you don't mind, pls send me your keystore/cert file so that I can check with my project. – BNK Oct 07 '15 at 13:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/91656/discussion-between-ssh-and-bnk). – SSH Oct 07 '15 at 19:36
  • Another link for "No peer certificate" exception http://stackoverflow.com/questions/16719959/android-ssl-httpget-no-peer-certificate-error-or-connection-closed-by-peer-e – BNK Oct 08 '15 at 01:09
  • was out for Uni exams, now back to work , I have tried with the above all stuff you provided, actually right now I have a mess of all ideas advices lolx..but atleast right now I am able to connect to my server with clientAuth="false", but I need this to be true for my case so when I change it to true, it starts giving me javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xa390b000: Failure in SSL library, usually a protocol error error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate (external/openssl/ssl/s3_pkt.c:1286 0xa39aac40:0x00000003) – SSH Oct 12 '15 at 12:09
  • sorry to bother you again but I am badly stuck with this, why i am not able to solve this issue as others have done it... – SSH Oct 12 '15 at 12:10
  • Can you send me your cert file or keystore file (with password) so that I can check tomorrow? My email is z10.blackberry@outlook.com – BNK Oct 12 '15 at 12:28
  • javax.net.ssl.SSLProtocolException: SSL handshake terminated: ssl=0xa390b000: Failure in SSL library, usually a protocol error error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate... Is this exception at server app? – BNK Oct 12 '15 at 12:54
  • Try reading this link http://ryepup.unwashedmeme.com/blog/2007/07/13/debugging-shibboleth-and-error14094412ssl-routinesssl3_read_bytessslv3-alert-bad-certificate-errors/ – BNK Oct 12 '15 at 13:00
  • Refer to the following link http://stackoverflow.com/questions/29916962/javax-net-ssl-sslhandshakeexception-javax-net-ssl-sslprotocolexception-ssl-han, your issue can be because of SSLv3? – BNK Oct 12 '15 at 14:28
  • thnx for your reply, I m working with the provided links, also I have sent you my keystore files – SSH Oct 13 '15 at 05:41
  • all of my keystores use the same password mentioned in may mail – SSH Oct 13 '15 at 05:43
  • I have replied your email :) – BNK Oct 13 '15 at 08:49
  • 1
    I have solved the issue by few modification to code, I have updated – SSH Oct 15 '15 at 10:35
  • 1
    Glad that you have solved your issue and thanks for sharing :) – BNK Oct 15 '15 at 10:54
  • can you tell me why that parameter you set to null and how it is working without keymanager – SSH Oct 15 '15 at 11:00
  • I think my code only works for self-signed ones, I will learn more with your new code – BNK Oct 15 '15 at 11:08
1

I have added the following class to solve the issue

import org.apache.http.conn.ssl.SSLSocketFactory;

import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 * Allows you to trust certificates from additional KeyStores in addition to
 * the default KeyStore
 */
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory{
    protected SSLContext sslContext = SSLContext.getInstance("TLSv1");

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(null, null, null, null, null, null);
        KeyManagerFactory keyManagerFactory = KeyManagerFactory
                .getInstance(KeyManagerFactory.getDefaultAlgorithm());;
        keyManagerFactory.init(keyStore, "123456".toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }



    /**
     * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
     */
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager {

        protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();


        protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {
            final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();

            try {
                // The default Trustmanager with default keystore
                final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                original.init((KeyStore) null);
                factories.add(original);

                for( KeyStore keyStore : additionalkeyStores ) {
                    final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                    additionalCerts.init(keyStore);
                    factories.add(additionalCerts);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }



            /*
             * Iterate over the returned trustmanagers, and hold on
             * to any that are X509TrustManagers
             */
            for (TrustManagerFactory tmf : factories)
                for( TrustManager tm : tmf.getTrustManagers() )
                    if (tm instanceof X509TrustManager)
                        x509TrustManagers.add( (X509TrustManager)tm );


            if( x509TrustManagers.size()==0 )
                throw new RuntimeException("Couldn't find any X509TrustManagers");

        }

        /*
         * Delegate to the default trust manager.
         */
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);
            defaultX509TrustManager.checkClientTrusted(chain, authType);
        }

        /*
         * Loop over the trustmanagers until we find one that accepts our server
         */
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for( X509TrustManager tm : x509TrustManagers ) {
                try {
                    tm.checkServerTrusted(chain,authType);
                    return;
                } catch( CertificateException e ) {
                    // ignore
                }
            }
            throw new CertificateException();
        }

        public X509Certificate[] getAcceptedIssuers() {
            final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
            for( X509TrustManager tm : x509TrustManagers )
                list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
            return list.toArray(new X509Certificate[list.size()]);
        }
    }

}
SSH
  • 1,609
  • 2
  • 22
  • 42
  • I have same problem. My code gives error in CertificateFactory cf = CertificateFactory.getInstance("X.509","BC") line. How can I use this class to avoid error? Thanks – Hilal Sep 20 '16 at 08:54
  • @Hilal Share you error trace, roughly i can suggest you to check your provider list, may be BC provider is not present in the list – SSH Sep 20 '16 at 09:07
  • 1
    I couldnt paste whole error because stackoverflow did not allow :) Also How can I check provider list? here is error; com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory$ExCertificateException 09-20 12:48:02.042 20236-20350/com.example.hilalinan.cert W/System.err: at com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory.engineGenerateCertificate(CertificateFactory.java:220) 09-20 12:48:02.042 20236-20350/com.example.hilalinan.cert W/System.err: – Hilal Sep 20 '16 at 09:51
  • I found out how to check provider list and couldnt see BC in the list.But I tried others instead BC but then I got NoSuchProviderException.For example:ACCVRAIZ1 I think I should write code version of them but dont know where to find? There are fields like COmmon name, Organization, Organizational unit, Serial number. None of them worked for me – Hilal Sep 20 '16 at 10:41
  • @Hilal Actually android only work with BC, so i sun think its gud to chng the provider, instead you have to add BC to the list, unfrtuntly i cnt send that code yet, u can google how to add BC to the list – SSH Sep 20 '16 at 10:50