Fail to use self-signed certificate in Android - android

It throws an exception like below
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
This Android program connects to my ASP.NET MVC deployed on IIS , and I create the .csr , .key , .crt file of my CA and my server's certificate using OpenSSL.
And I convert the .crt file of my server's certificate to .pfx format and import it in IIS .
I found the solution on Android Developer .But my code is similar to the code it lists .
CertificateFactory cf = CertificateFactory.getInstance("X.509","BC");
InputStream caInput = getResources().openRawResource(R.raw.root); //here "R.raw.root" is a .bks file converted from my CA's .crt file , and a .bks file converted from my server's .crt file , but both throw this exception
Certificate ca;
try
{
ca = cf.generateCertificate(caInput);
} finally
{
caInput.close();
}
// Create a KeyStore containing our trusted CAs
//String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance("BKS");
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(),null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://172.18.13.178:63123/Home/Test");
HttpsURLConnection urlConnection =(HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
//omit other code
}
The Android Developer says this is the solution of this error , but I write my code similar to it , but it fails.
So anyone tell me where the problem is ? The way Android Develop gives does not work .

Related

Android, MQTT: broker certificate expiration

My app connects to mqtt broker using certificate file through ssl connection.
I setup the certificate file (.crt) and the key file (.key) in my broker.
I use Paho Mqtt Client api, and this api needs a SSLSocketFactory to establish connection.
I use a Google example to create a SSLSocketFactory instance with a TrustManager who trust our CA in a keystore.
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(new
FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
Everything works fine right now. BUT, the certificate is going to expire in 5/30/2017.
How do i must deal with the certificate in the client side (Android)?
I've have tested in testing environment with a new certificate. The app can't connect to broker. Exception is:
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
How can a deal with certificate renewal on Android?
I have request a new certificate using the same .key file and all clients did not have any issue connecting to broker with the new .crt.
But, is it safe to use the same key for certificate renewal?

Install a certificate for opening site inside a Webview?

I have a website which I want to open in an Android Webview. The website uses a certificate emitted by COMODO RSA Domain Validation Secure Server CA. The problem is that I get an Unkown Certificate Error for devices all running a version less than (including) Android 5.
I serched in the documentation and as far as I understood the problem is that the CA was created before the release of Android 5.
I could do a handler.proceed(); on onReceivedSslError but I want to keep the app secure and I think Google can reject the app on play store anyway.
I found that I cound do something like this
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
but the problem is that my code is like so
myWebView.loadUrl("https://site.domain.com")
How can I install the certificate of the CA within my Webview?
Thanks
You need to override method to your WebViewClient implementation. Try this:
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) { handler.proceed(); }
Also, it could be with the SSL certificate installed on the website that you wish to run on webview. The SSL certificate provided by the authority is not supported on mobile, assuming if there's no error viewing the website on a desktop.

Trust anchor for certification path not found exception

Hi I'm trying to establish ssl communication between tomcat server and android app using https
1- I used keytool to create a keystore file for tomcat
2- then generate a pem file to use it with keytool to generate a BKS file
3- the tomcat server is working fine
basically I followed this article
The problem is when I try to Connect from android app using HttpsURLConnection I always get the exception :
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:351)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:1323)
at com.android.okhttp.Connection.connect(Connection.java:1225)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:395)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:298)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:399)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:110)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:221)
at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:25)
at org.apache.cordova.rest.Rest.send(Rest.java:177)
help !!
Two possible solution
1) If you are using Self Signed Certificate try adding the certificate (.crt / .cer) to the truststore.
2) If your certificate is signed by your local CA make sure you import the root CA and intermediate CA to the trust store.
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getApplicationContext().getResources()
.openRawResource(R.raw.my_certificate);//new BufferedInputStream(is);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
} finally {
caInput.close();
}
/** Create a KeyStore containing our trusted CAs **/
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
/**Create a TrustManager that trusts the CAs in our KeyStore **/
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
/** Create an SSLContext that uses our TrustManager **/
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
and finally set the sslcontext to your HttpsURLConnection

Do we need to create any certificate to call https web service in Android

Hi I am working on android application where I am using https protocol in all the web service. so to communicate with https enabled server from android app do we need to add any certificate in my raw folder of android ?
If yes then what is the process of it. I checked many answers but people are simply ignoring the https procotol just accepting all certificates or by pass.
Thanks in advance.
Create BouncyCastle KeyStore, put your certificate in it (you can use openssl), later put created KeyStore into res/raw folder.
In app:
Load your keystore file into java KeyStore
Feed your HttpClient with your KeyStore
Example:
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
source:
https://developer.android.com/training/articles/security-ssl.html

Untrusted SSL certificate - Custom keystore issues

I have my own PKI infrastructure for my web server with a CA and an intermediate CA. Then I have a web certificate signed by the intermediate CA and I want my app to communicate with the server. According to the Developer docs the solution is to create my own keystore. So I bundled the root CA certificate with the app and tried to see if that would work. It didnt, and I got the following error:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
So my question is this. Since the SSL certificate is signed by my intermediate CA, is that the certificate I should be importing into the custom key store, or do I need both, or is there something else wrong here?
Ultimately, with a SSL certificate signed by a CA not trusted by Android, is this the right way to go about it?
Thanks!
Here's the code that sets up the keystore manager.
public SSLContext getTrusted() throws Exception{
// Load CAs from an InputStream
CertificateFactory cf = CertificateFactory.getInstance("X.509");
AssetManager assManager = context.getAssets();
InputStream is = null;
try {
is = assManager.open("ca.cert.crt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
InputStream caInput = new BufferedInputStream(is);
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
Log.d("TrustMan", "ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context;
}
And then I am trying to use it as follows.
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
TrustMan tm = new TrustMan(context);
SSLContext sslContext;
sslContext = tm.getTrusted();
connection.setSSLSocketFactory(sslContext.getSocketFactory());
The code did actually work, but not when I returned the SSLContext from my class. I adjusted the class to return the TrustManagerFactory instead, and using the intermediate CA certificate works fine now!
Thanks!

Categories

Resources