I\'m building a small program that acts as an XMPP client and I am using the Smack library. Now, the server I am connecting to requires SSL (in Pidgin I have to check \"Forc
You can achieve this by the following:
Storing the CA Certificate in Keystore
To store the certificate in a Keystore follow these steps.
Step 1: Download the bouncycastle JAR file. It can be downloaded from the here: Bouncy Castle JAVA Releases
Step 2: Use the following command to store the certificate in keystore
keytool -importcert -v -trustcacerts -file "<certificate_file_with_path>" -alias "<some_name_for_certificate>" -keystore "<file_name_for_the_output_keystore>" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "<bouncy_castle_jar_file_with_path>" -storetype BKS -storepass "<password_for_the_keystore>"
Step 3: Verify the keystore file
keytool -importcert -v -list -keystore "<file_name_for_the_keystore_with_path>" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "<bouncy_castle_jar_file_with_path>" -storetype BKS -storepass "<password_for_the_keystore>"
This shall list us the certificate included in the keystore.
We have a keystore which we can use in our code.
Using the keystore
After generating this keystore, save it in the raw folder of your application. The use the below code to get the certificate handshake with the openfire server.
To create a connection with openfire using XMPP, you may need to get the config. For the same, use the below method:
public ConnectionConfiguration getConfigForXMPPCon(Context context) { ConnectionConfiguration config = new ConnectionConfiguration(URLConstants.XMPP_HOST, URLConstants.XMPP_PORT); config.setSASLAuthenticationEnabled(false); config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled); config.setCompressionEnabled(false); SSLContext sslContext = null; try { sslContext = createSSLContext(context); } catch (KeyStoreException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (KeyManagementException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } config.setCustomSSLContext(sslContext); config.setSocketFactory(sslContext.getSocketFactory()); return config; } private SSLContext createSSLContext(Context context) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, IOException, CertificateException { KeyStore trustStore; InputStream in = null; trustStore = KeyStore.getInstance("BKS"); if (StringConstants.DEV_SERVER_IP.equals(URLConstants.XMPP_HOST) || StringConstants.TEST_SERVER_IP.equals(URLConstants.XMPP_HOST)) in = context.getResources().openRawResource(R.raw.ssl_keystore_dev_test); else if(StringConstants.STAGE_SERVER_IP.equals(URLConstants.XMPP_HOST) || StringConstants.STAGE2_SERVER_IP.equals(URLConstants.XMPP_HOST)) in = context.getResources().openRawResource(R.raw.ssl_keystore_stage); else if(StringConstants.PROD_SERVER_IP.equals(URLConstants.XMPP_HOST) || StringConstants.PROD1_SERVER_IP.equals(URLConstants.XMPP_HOST)) in = context.getResources().openRawResource(R.raw.ssl_keystore_prod); trustStore.load(in, "<keystore_password>".toCharArray()); TrustManagerFactory trustManagerFactory = TrustManagerFactory .getInstance(KeyManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom()); return sslContext; }
All done..!! Just connect.. Now your connection is secured.
All follow the same in my blog at smackssl.blogspot.in
Yes, it's quite easy to achieve. Take a look at the ConnectionConfiguration class, and in particular the setSecurityMode method which accepts a ConnectionConfiguration.SecurityMode enum as a parameter. Setting this to "required" forces Smack to use TLS.
from the Javadoc:
Securirty via TLS encryption is required in order to connect. If the server does not offer TLS or if the TLS negotiaton fails, the connection to the server will fail.
Take a look at this thread.
http://www.igniterealtime.org/community/thread/37678
Essentially, you need to add these two lines to your code:
connConfig.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);
connConfig.setSocketFactory(new DummySSLSocketFactory());
where connConfig is your ConnectionConfiguration object. Get the DummySSLSocketFactory from the Spark source code repository. All it does is accept virtually any certificate. This seemed to work for me. Good luck!