Implementing SSL in MQTT Android connection - android

I have a question related to the use of MQTT protocol in Android environment. We are developing an Android application and using com.ibm.micro.client.mqttv3_7.5.0.0.jar MQTT client library in order to send push notifications to Android devices. My question is about SSL connection. In desktop applications, we copy our .keystore file in a proper location and refer to it as follows;
public Properties getSSLSettings() {
final Properties properties = new Properties();
properties.setProperty("com.ibm.ssl.keyStore",
"C:/BKSKeystore/mqttclientkeystore.keystore");
properties.setProperty("com.ibm.ssl.keyStoreType", "BKS");
properties.setProperty("com.ibm.ssl.keyStorePassword", "passphrase");
properties.setProperty("com.ibm.ssl.trustStore",
"C:/BKSKeystore/mqttclienttrust.keystore");
properties.setProperty("com.ibm.ssl.trustStoreType", "BKS");
properties.setProperty("com.ibm.ssl.trustStorePassword", "passphrase ");
return properties;
}
Above code works perfectly to get SSL settings. We implemented this code also in Android, but it is very clear that holding .keystore file(s) inside the device is not secure at all. My question is, is there any other alternative to implement SSL connection without storing .keystore file(s) inside device’ s internal or external storages?

In later versions of android you can access the device's keystore using KeyChain to provide access to private keys. For the trust store using the device's trust store works fine, which android uses by default for SSL connections. Also IBM have a messaging community which has information on using their libraries on mobile devices.

Related

Custom IoT Endpoint

We need to use a custom IoT endpoint due to firewall restrictions and needing to utilize Static Ips. We followed this AWS doc to get our endpoint with static Ips.. From here we are attempting to call the CreateKeysAndCertificate via Java. Now when we call IoT with our custom domain name, iot.custom.domain.name.com, with the regular Java SDK it works fine. However, whenever we try to use the Android SDK and call setEndpoint with our custom domain we get the following error
com.amazonaws.services.iot.model.ResourceNotFoundException: Not Found (Service: AWSIot; Status Code: 404; Error Code: ResourceNotFoundException
Any help or guidance on this would be appreciated.
When using the Android SDK for establishing IOT connections, the CreateKeysAndCertificateRequest API is available through the AWSIotClient class. If you are using the AWSIotClient for creating new certs/keys, the SDK places this request on the generic iot.<region>.amazonaws.com endpoint. The setEndpoint method just allows you to change the region. This is because the request goes to the Control plane, whereas the endpoint that you have created would mostly likely be on the Data plane. There is no way around to create new certs/keys using the AWSIotClient on the custom endpoint.
There is an alternate option that you can make use of. Almost all "requests" that you place on the IOT endpoint are messages that are published to "reserved topics". If you open up the Java SDK's PublishCreateKeysAndCertificate API, you will see that it is ultimately publishing a message over a reserved topic. You can do something similar on Android using the Android SDK as well.
First, you will have to establish an authenticated connection. We cannot use CognitoCredentialsProvider because of that auth request going to the Control Plane. Instead, you can use the provisioning certificates for the first time authentication. This is through provision certificates generated for a Provisioning Fleet. You can create a Provisioning Fleet and use those certificates in your device's keystore (or, a PKCS12 cert file). Using that, you can create a new awsIotMqttManager object and publish a message on the reserved topic meant for creating new certs/keys. You can also subscribe to reserved topics meant for receiving the "accepted"/"rejected" responses for this request.
TL;DR
Create an awsIotMqttManager using the provision certs
Subscribe to topic for listening for accepted/rejected response for CreateKeysAndCertificates request
Publish a message over the reserved topic meant for CreateKeysAndCertificates
Register the thing using the ownershipToken received in the response
Store the new certs and use them for all future connections (make sure the policy attached to the certs have the necessary permissions)

Pusher on Android

I'm trying to get Pusher working on Android. Here are my needs.
Must support "private-" channels
Must support secure connections
Must be able to override the pusher/auth endpoint.
Note: I've already tried the following routes....
loading pusher.js in a WebView and letting it fall back to SockJS
https://github.com/pusher/pusher-phonegap-android (Does not seem to support secure connections)
https://github.com/EmoryM/Android_Pusher/blob/master/src/com/emorym/android_pusher (Requires a private key to be pushed to the client, also not up to date)
https://github.com/jmschultz/JavaPusherClient (Does not support private channels)
Anyone else have any luck with this?
Pusher have a Java library: https://github.com/pusher/pusher-java-client
There's a very simple sample application here:
https://github.com/pusher/pusher-android-example
You can tell the Pusher instance to use an encrypted connection via PusherOptions. See:
https://github.com/pusher/pusher-java-client/blob/master/src/main/java/com/pusher/client/PusherOptions.java#L24
I think this is likely to be updated to be the default, or at least reconnection will try over SSL if an unencrypted connection fails.

Using HTTPS to encrypt data sent from mobile

I have an app that is on both Android & iOS. To encrypt the data that is sent to a PHP script, from the app side of things, is it just a case of adding an "S" to "HTTP://....." and then everything is encrypted when sent up?
Tried Google but couldn't find anything related. Thanks.
No you can't just add an s.
the 's' in https signifies that the connection is secured by TLS (Transportation Layer Security) . This is achieved via authentication using certificates and Public Key Cryptography.
See:
http://computer.howstuffworks.com/encryption.htm
http://en.wikipedia.org/wiki/Public-key_cryptography
for IOS specific implementations see
https://developer.apple.com/library/ios/#documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html#//apple_ref/doc/uid/TP30000897-CH204-TP9

Using certificates in android client

I want to establish an ssl communication to the server from my android client.
this is what I've done so far:
1 Created a a pair of public private keys using java keytool genkey(and in the process created a self signed certificate)
2. Exported the public key and imported the public key in to another keystore(called customkeystore)
Now I want to use this customkeystore file as my truststore. Where should I place this file in my android client and how to make it aware of the path of this trustore and access it.
Don't know Android but I would imagine that you just load your keystore like in any Java application.
This is what happens here SSL through Android and here SSL Verification Android

Android - Custom SSL certificate chain checking without bundling keystore with the app

I am after a solution which would enable me to use the in-build keystore and StrictHostnameVerifier but would allow me to obtain the X590CertificateChain (either once connected or post handshake) so I can perform some additional checks (specifically I want to verify the root public key is the one I expected).
The examples I have investigated are mainly around overriding the behaviour (i.e. by replacing the socket factory or hostname checker with ones which don't do anything) and I am struggling with the differences between the android and other java implementations.
The reason I don't want to bundle a keystore (aside from having to use bouncycastle instead of jks) is that I don't want to package the intermediate CA cert with the app as this will create a certificate management problem sooner.
Many thanks in advance for any comments.
Ideally, this should be done at runtime. Bundling the certificate might be redundant as well, when some devices might already have that certificate installed.
Normally, your approach should be this.
Try connecting to the server.
If certificate is not installed, you will get a certificate exception. Catch it, extract the public certificate, save it, by creating a keystore on the fly.
While making new connections, use this keystore to initialize your SSL context.

Categories

Resources