Note that there are some explanatory texts on larger screens.

plurals
  1. POTwo way SSL authentication on android
    primarykey
    data
    text
    <p>I am trying to get two way SSL authentication working between a Python server and an Android client application. I have access to both the server and client, and would like to implement client authentication using my own certificate. So far I have been able to verify the server certificate and connect without client authentication.</p> <p>What sort of certificate does the client need and how do I get it to automatically send it to the server during the handshake process? Here is the client and server side code that I have so far. Is my approach wrong?</p> <p>Server Code</p> <pre><code>while True: # Keep listening for clients c, fromaddr = sock.accept() ssl_sock = ssl.wrap_socket(c, keyfile = "serverPrivateKey.pem", certfile = "servercert.pem", server_side = True, # Require the client to provide a certificate cert_reqs = ssl.CERT_REQUIRED, ssl_version = ssl.PROTOCOL_TLSv1, ca_certs = "clientcert.pem", #TODO must point to a file of CA certificates?? do_handshake_on_connect = True, ciphers="!NULL:!EXPORT:AES256-SHA") print ssl_sock.cipher() thrd = sock_thread(ssl_sock) thrd.daemon = True thrd.start() </code></pre> <p>I suspect I may be using the wrong file for ca_certs...?</p> <p>Client Code</p> <pre><code> private boolean connect() { try { KeyStore keystore = KeyStore.getInstance("BKS"); // Stores the client certificate, to be sent to server KeyStore truststore = KeyStore.getInstance("BKS"); // Stores the server certificate we want to trust // TODO: change hard coded password... THIS IS REAL BAD MKAY truststore.load(mSocketService.getResources().openRawResource(R.raw.truststore), "test".toCharArray()); keystore.load(mSocketService.getResources().openRawResource(R.raw.keystore), "test".toCharArray()); // Use the key manager for client authentication. Keys in the key manager will be sent to the host KeyManagerFactory keyFManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyFManager.init(keystore, "test".toCharArray()); // Use the trust manager to determine if the host I am connecting to is a trusted host TrustManagerFactory trustMFactory = TrustManagerFactory.getInstance(TrustManagerFactory .getDefaultAlgorithm()); trustMFactory.init(truststore); // Create the socket factory and add both the trust manager and key manager SSLCertificateSocketFactory socketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory .getDefault(5000, new SSLSessionCache(mSocketService)); socketFactory.setTrustManagers(trustMFactory.getTrustManagers()); socketFactory.setKeyManagers(keyFManager.getKeyManagers()); // Open SSL socket directly to host, host name verification is NOT performed here due to // SSLCertificateFactory implementation mSSLSocket = (SSLSocket) socketFactory.createSocket(mHostname, mPort); mSSLSocket.setSoTimeout(TIMEOUT); // Most SSLSocketFactory implementations do not verify the server's identity, allowing man-in-the-middle // attacks. This implementation (SSLCertificateSocketFactory) does check the server's certificate hostname, // but only for createSocket variants that specify a hostname. When using methods that use InetAddress or // which return an unconnected socket, you MUST verify the server's identity yourself to ensure a secure // connection. verifyHostname(); // Safe to proceed with socket now ... </code></pre> <p>I have generated a client private key, a client certificate, a server private key, and a server certificate using openssl. I then added the client certificate to <code>keystore.bks</code> (which I store in <code>/res/raw/keystore.bks</code>) I then added the server certificate to the <code>truststore.bks</code></p> <p>So now when the client tries to connect I am getting this error server side:</p> <pre><code>ssl.SSLError: [Errno 1] _ssl.c:504: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate </code></pre> <p>And when I try to do this in the android client</p> <pre><code>SSLSession s = mSSLSocket.getSession(); s.getPeerCertificates(); </code></pre> <p>I get this error:</p> <pre><code>javax.net.ssl.SSLPeerUnverifiedException: No peer certificate </code></pre> <p>So obviously the keystore I am using doesn't appear to have a correct peer certificate in it and thus isn't sending one to the server.</p> <p>What should I put in the keystore to prevent this exception?</p> <p>Furthermore, is this method of two way SSL authentication safe and effective?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload