Im having problem connecting to a mqtt server using self signed certificate. im using Paho client and want to connect to a server using a TLSv1.2
. actually i was successful to connect in Android APIs 20+ but no success for below this version.
what ive done till now :
1- created a PKCS#12 keystore and put the .crt file and assing a password to it and save it (it will be a .pfx file)
2- added the .pfx file to raw folder of recourse in android project
3- used below code to load self signed certificate:
connection = createConnection(mqttCallback);
MqttConnectOptions connOpts = optionsFromModel(connectionModel);
connOpts.setSocketFactory(getSSLSocketFactory(keyStoreInputStream, keyStorePassword));
connection.addConnectionOptions(connOpts);
and the getSSLSocketFactory
method which is the most important part is :
public SSLSocketFactory getSSLSocketFactory (InputStream keyStore, String password) throws MqttSecurityException {
try{
SSLContext ctx = null;
SSLSocketFactory sslSockFactory=null;
KeyStore ks;
ks = KeyStore.getInstance("PKCS12");
ks.load(keyStore, password.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(ks);
TrustManager[] tm = tmf.getTrustManagers();
ctx = SSLContext.getInstance("TLS");
ctx.init(null, tm, null);
sslSockFactory = ctx.getSocketFactory();
return sslSockFactory;
} catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException | KeyManagementException e) {
throw new MqttSecurityException(e);
}
}
this works perfectly but no success in Android APIs below 20.
finally found a solution to this.
based on this documentation, TLS 1.1 and TLS 1.2 is supported from android API level 16 (Android 4.1, Jelly Bean). But it is'nt enabled by default until API level 20+ (Android 4.4 for watch, Kitkat Watch and Android 5.0 for phone, Lollipop).
so all we need is to enable them parogrammatically in code. how we gonna do this ? there is a solution for this problem here BUT it just resolves the problem for the case that you want to accept any certificate instead.
what we need is do the same thing but with our own self signed certificate. so we do it like below. the first part is just like what i did before : (
keyStoreInputStream
is input stream of a .pfx file)the
getSSLSocketFactory
method changes to:and the
TLSSocketFactory
class is like below: