Enabling HTTPS communication between my server and my client - android

I have already built a server app and an android app. So far they were communicating over http, but I am sending sensitive information in each request (like JWT). Therefore I neet to use Https instead.
I have generated a p12 certificate.
On the server side:
I've copied the certificate to resources/keystore/sampleName.p12
I've added these lines to my application.properties
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=samplePassword
server.ssl.key-store=classpath:keystore/sampleName.p12
server.ssl.key-alias=sampleName
On android side I use okHttp and create the client like this
val httpClient = OkHttpClient.Builder()
.certificatePinner(
CertificatePinner.Builder()
.add(
https://10.0.2.2:8080,
"sha256/lVIcG+gpmlabsq1bW5RbvB+kqVSHKdOFyoxjo9+SLEs="
).build()
)
.build()
I use https://10.0.2.2:8080 because I run the server app only localy and I also run the android app on an emulator on the same laptop.
To get sha256/lVIcG+gpmlabsq1bW5RbvB+kqVSHKdOFyoxjo9+SLEs= I've used keytool -list -v -keystore sampleName.p12 -storetype PKCS12 -storepass samplePassword and converted the sha256 fingerprint which was in hex to base64.
Now when I try to send any request to the server I get an
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
I am clearly missing something but I dont know what. Is there anything else I need to do? Or did I do something wrong? Or is it just not supposed to work localy?
Note that this is just an exercise for me and I won't be actually deploying the server app on any real server and I won't release the android app.
But still I will be presenting the solution and I really nedd it to be solid and work localy.

CertificatePinning is in addition to the normal certificate checks. It only further restricts the choice of certificate, since be default you will accept any cert for your host.
See Adding a custom certificate to an OkHttp Client for an existing answer.
Or read up here
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-certificate-pinner/

Related

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException

i need to get echo value i.e (yes or no) from php file to myresulttextview but unable to retrieve it says error :"com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. "
val barcode = data.getParcelableExtra<Barcode>(BarcodeCaptureActivity.BarcodeObject)
val p = barcode.cornerPoints
var m = barcode.displayValue.toString().trim()
val jsonobj=JSONObject()
jsonobj.put("email",m)
val url="https://192.168.2.11/verf1.php"
val que=Volley.newRequestQueue(this#MainActivity)
val req=JsonObjectRequest(Request.Method.POST,url,jsonobj,Response.Listener {
response ->mResultTextView.setText(response.toString())
},Response.ErrorListener {
response ->mResultTextView.setText(response.toString())
})
que.add(req)
my php file
<?php
require "conn.php";
$user_name=false;
if(isset($_POST["email"])){
$user_name = $_POST["email"];
}
$mysql_qry="select * from exitpass where email like '%".$user_name."%'";
$result=mysqli_query($conn,$mysql_qry);
if(mysqli_num_rows($result)>0)
{
echo"yes";
}
else{
echo"no";}
?>
The error is related to the TLS/SSL certificate associated with your 192.168.2.11 web server. There are a few different ways to solve this problem depending on what your setup is like.
If you have no cert installed on your web server then replace https with http to send over an unencrypted channel.
val url="http://192.168.2.11/verf1.php"
If the web server does have a cert installed then you could have a few issues. Common issues related to the stack trace are invalid certs, using the wrong (or no) domain name, wrong Java code for the encryption type and Java version, issue somewhere in the trust chain, expired cert, etc.
In summary, I believe you simply need to send over http, but if that doesn't work, you should troubleshoot it in this order.
Change the IP to the domain name associated with your cert
Verify you can access your resource in the browser and that the certificate is not expired
Figure out what type of encryption you are using (TLS 1.1, TLS 1.2, etc) and what Java you are using (1.6 or 1.7). There is a key difference between Java 6 and Java 7 as it relates to accessing TLS encrypted resources and I explain it in my highest rated post (as a reference).
If all else fails you will likely need to manually install the certificate in Androids JVM trust store. I believe you can do this from most GUIs and definitely from the terminal if you have access. You shouldn't have to do this, but sometimes you are forced to if the certificate chain breaks. It might not even be your cert causing the issue, it can be any cert in your trust chain.
Please let me know if the initial suggestion works. If it doesn't work please provide the public cert here ( or just the domain name and I will pull it down) and your Java version and I can better assist.

Unexpected exception while opening secure websocket connection

I'm trying to open a secure websocket connection from a Xamarin Android application to an IIS server. It works fine and dandy on every device I've ever used except Samsung Tab E. Even other Samsung devices work fine.
I'm using the Websockets.PCL library and the regular code:
var _webSocket = WebSocketFactory.Create();
_webSocket.OnOpened += _webSocket_Opened;
_webSocket.OnError += _webSocket_Error;
_webSocket.Open("wss://server.name.here/path/also/");
In this case the error handler is called with:
[websockets] javax.net.ssl.SSLException
[websockets] javax.net.ssl.SSLException: Error occured in delegated task:javax.net.ssl.SSLException: Unexpected exception
The device has no issues with SSL connections via Chrome or other apps, not to this server or others. It also has no issues connecting via SignalR to the same IIS server from this application.
It does have an issue when another third party library is trying to check license from a separate website and an error is logged:
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x803b3b28: Failure in SSL library, usually a protocol error
I don't know which address it's trying to contact so can't check what is happening there. But this also works from other devices.
This leads me to believe the Android in the Tab E (v4.4.4, latest available) has something wrong with its SSL implementation since these two connection attempts through javax.net.ssl are failing. But the unexpected exception isn't giving much information.
How to get around this? I wouldn't mind using the websockets implementation SignalR uses (since it works), but as far as I know it's not really exposed as a general use system ready to use.
Additional info
The server does talk TLS1 nicely and sends the whole certificate path as far as I know it, so that shouldn't be the issue, unless the root isn't known (and I would expect to get the handshake failure if that was the case). Testing with openssl shows:
Certificate chain
0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=our.domain.com
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
No client certificate CA names sent
Server Temp Key: ECDH, P-256, 256 bits
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Unfortunately openssl doesn't support the ยด-ssl2` flag anymore. Online tools say that SSL2 is disabled, SSL3, TLS1, TLS1.1 and TLS1.2 are enabled.
I could try the custom SSLSocketFactory route but have to see how it would go through Xamarin and Websockets.PCL.
I found a solution for my case after searching for SSL issues in Android. Florian Krauthan has written about these things and talks about using the SSLSocketFactory on Android 4.1+ to allow use of TLS1.1 etc.
This led me to another post where he explains how Google Play Services can be used to inject a newer OpenSSL library into the whole application. This method also worked for my issue.
The only thing that needs to be done is to add the following code to the beginning of the main activity's OnCreate() method:
Android.Gms.Security.ProviderInstaller.InstallIfNeeded(this);
After this the application will use Google Play Services' OpenSSL library so all connections work without issues and possible known bugs in the built-in Android OpenSSL library get mitigated since a newer version is used.
Of course this might not be a solution for anyone not already using Google Play Services since it increases the application size tremendously.

Android: Authenicating with certificates for Exchange Server using HTTP Methods

I am trying to sync with my exchange server using HTTP Methods(HttpPost) with the client certificate (abc.pfx) which is generated by the server. I tried using KeyStore, KeyManagerFactory,TrustManagerFactory and SSLSocketFactory to acheive this. But iam getting
Authentication Error (If i trust all certificates) Received authentication challenge is null
java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. (If i trust only the server (Root CA) cert).
I had gone through many Links in StackOverflow 1,2,3,4. If u can see all the links are atmost same. I tried different ways but still no use.
Note: I am using abc.pfx (it is not self signed), server.cer (to make this trust). Iam converting both file into BKS format and using in my code. Plz help me to solve this problem

How can I validate a PEM encoded server certificate and chain agains the Android trusted CAs?

I am developing an enterprise communications app to run on Android 4.0+. This app has a native transport layer written in c/c++ which manages the SSL connections with a SIP server. The native layer uses openSSL libraries for the SSL connection.
I need to implement validation of the server certificate when the app opens an SSL connection. This includes validating the certificate chain against available root CA certificates and hostname validation. My problem is that there is no access (that I am aware of) to Androids trust store CA certificates. By this, I mean the built-in certificates (e.g. Verisign) and user installed trusted CAs.
Therefore, I am pretty sure what I have to do is pass the certificate chain up to the java code (this is implemented and working) so that I can use the java security APIs. Essentially, what I have to start with is an array of certificates (the chain received from the server) in PEM format (could be DER, if that was better).
I understand how I can convert the chain into Certificate objects and the Certificate objects into a CertPath object. It looks like one can then use the CertPathValidator to validate the CertPath. Am I on the right track? The point at which I am hung up here is that CertPathValidator.validate(cp,params) takes a PKIXParameters object. This, in turn, seems to need either a keystore or a Set of TrustAnchors. I assume that the keystore or set of TrustAnchors represents the trusted root CAs that are to be used to validate cp (the CertPath), correct? If so, how/where do I get the input parameters for the PKIXParameters constructor?
On another tack, I just started looking into whether a TrustManager could/should be used to validate the server certificate. I think I understand how TrustManagers fit in and are used when working with an HTTPSUrlConnection, but it is not clear how I might do this when all I start with is my array of PEM certificates.
Can someone point me in the correct direction?
Thanks,
Ken

Using UnboundID SDK with an SSL certificate file to connect to LDAP server in Android app

I'm trying to make a connection to an LDAP server in my Android app, and am using the UnboundID SDK. Recently, a change was made from unsecured to secured LDAP, and I have to change the app accordingly. I have been given the SSL certificates file to validate against. I've already used the file to make a keystore as described here. I've got this keystore file in the assets folder of my app, and am pulling from that. The code below does not currently work, and throws the exception:
LDAPException(resultCode=01 (connect error), errorMessage=('An error occurred while attempting to connect to server place.myserver.com:636: javax.net.ssl.SSLHandShakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
// code from above link
AssetManager assetManager = getApplicationContext().getAssets();
InputStream keyStoreInputStream = assetManager.open("yourapp.store");
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(keyStoreInputStream, "myPassword".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
// my code
SSLUtil sslUtil = new SSLUtil(tmf.getTrustManagers());
LDAPConnection connection = new LDAPConnection(sslUtil.createSSLSocketFactory());
connection.connect("place.myserver.com", 636);
However, the code segment:
SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager());
LDAPConnection connection = new LDAPConnection(sslUtil.createSSLSocketFactory());
connection.connect("place.myserver.com", 636);
does work (although I was informed by the higher-ups that this would be insecure).
I'm not quite sure as to what exactly I'm doing wrong here, so any help would be appreciated. Also, if there is a better way of accomplishing this than what I'm attempting to do above, feel free to let me know :) I would like to stick with the UnboundID library though, since the rest of the code is already written using that as well, and everything works if I use the TrustAllTrustManager.
It's true that the trust all trust manager isn't secure. It's convenient for testing purposes, but it will allow a bad guy to set up his own server with a certificate he generates for himself and use it to impersonate the real server, or to operate as a man in the middle, intercepting and potentially alerting any communication between the client and the real server. With a more strict trust manager in place, the client should reject the bogus certificate that the fake server will present.
Unfortunately, though, it looks like the trust manager you're trying to use in this case doesn't like the certificate that your server is presenting to it. Because the trust all trust manager allows you to establish the connection, that means that your server does have a certificate and is capable of performing SSL communication, but there's something about that certificate that your trust manager doesn't like. It's almost certainly not an issue with the LDAP SDK, since the same problem should arise with any other LDAP API if you're using the same trust store.
If you look at the result, it has a message of "Trust anchor for certification path not found". This implies that neither the certificate the server is using nor those of any of its issuers was found in the trust store. You'll need to import the server certificate (or the certificate of one of its issuers) into the trust store that you're using. It sounds like you've tried to do that, but since it's not working then something must not be quite right with the way it was done. I'd recommend working wit the directory server administrator to ensure that you're trying to import the right certificate based on the server configuration.

Categories

Resources