How to create an SSL connection using the Smack XMPP library?
Solution 1
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
Solution 2
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.
staffan
I'm the serviceability architect/tech lead for the Java SE platform at Oracle. I've previously been the chief architect for JRockit.
Updated on June 28, 2022Comments
-
staffan almost 2 years
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 "Force old (port 5223) SSL"). I'm having trouble getting Smack to connect to this server. Is it possible?
-
Alastair Brayne about 8 yearsWhat are the
Context
andR
classes? -
Iqbal S about 8 years@Alastair
Context
is the application or class level context, which you can pass usingthis
. AndR
is a class from which I get the key stores stored in my hard drive in the raw directory, you can directly pass that resource to the in by any other means as you like too. -
Alastair Brayne about 8 yearsSounds like you're working in a specific framework. Android? I'm not, so this just confused me for a bit. But I figured it out. Thanks anyway.
-
Iqbal S about 8 yearsYes you are correct, the code is domain specific, but you can apply the same to any domain. Small changes required. Hope you felt the answer helpful, upvote shall be appreciated. ;-) Thanks.
-
Priya over 7 years@Iqbal, will this cetificate ask persmission from the user to allow ?
-
Iqbal S over 7 years@Priya In Android all the permissions are asked when the user installs the application, so we do not ask any permission for the user. If you are working on a different framework, or even in Android if you want to ask the permission from the user, then you can do it before loading the trust store, using a confirm box, to ask user wants to continue by loading it or no.. Hope this helps!!
-
Priya over 7 yearsthank u Iqbal.., what does <certificate_file_with_path> meant her ?
-
Iqbal S over 7 years@Priya it is the local path of your certificate with full name.