I have developed an android app where I am accessing one server url to access one xml file.In that server we have deployed one SelfSigned SSL Server Certificate.
I tried this code
// My Code:
My Code is here as follows
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = this.getResources().openRawResource(R.raw.server2); //server2 is the server2.crt Certificate file
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
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
But I am getting "javax.net.ssl.SSLHandshakeException: Handshake failed" Error.PLease help me how to access that URL?
Related
I want to set a custom SSL certificate for my UrlTileProvider from the Google Maps Android API.
In my subclassed UrlTileProvider I'm setting the URL to the WMS of my Geoserver by https.
Can you tell me how to set the SSLContext by UrlTileProvider in order to use my SSL certificate?
I found the solution!
if I do not set the SocketFactory directly to a specific connection - I can define my socket factory as the DefaultSSLSocketFactory for HttpsURLConnections in general.
See:
Instead of applying this function:
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
I can add the Socket Factory per Default:
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = mContext.get().getAssets().
open("mycert.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);
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
I check the certificate which is stored in app side and server side both are matching or not only trusted certificate should work
Below is my code and that code I am getting error in setDefaultSSLSocketFactory
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.cert));
Certificate ca = cf.generateCertificate(caInput);
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 sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
urlConnection = (HttpURLConnection) url.openConnection();
(HttpsURLConnection)urlConnection).setDefaultSSLSocketFactory(sslContext.getSocketFactory());
urlConnection.setRequestMethod(params[1]); //POST or GET
urlConnection.setRequestProperty("Content-type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setConnectTimeout(Constant.TIMEOUT_CONNECTION);
urlConnection.setRequestProperty("Authorization", basicAuth);//auth value
setDefaultSSLSocketFactory I am getting error cannot resolve method; where am I am going wrong? I have check the certificate both side certificate which is used in url and certificate which I am having but in setDefaultSSLSocketFactory is showing error so I cannot avail to test.
Update
I resolve the issue of cannot resolve method setDefaultSSl but now I am getting exception:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
My Android application is having Couch Base Lite Replication. Using earlier versions I was able to add SSL Certificate and sync, but when I updated to version 1.3.1 the classes got deprecated and now i am not able to add certificates. Any Help?
Found the Solution
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
AssetManager assManager = Utils.context.getAssets();
InputStream is = null;
is = assManager.open("certificate.cer");
InputStream caInput = new BufferedInputStream(is);
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 CouchbaseLiteHttpClientFactory
CouchbaseLiteHttpClientFactory cblHttpClientfactory = new CouchbaseLiteHttpClientFactory
(database.getPersistentCookieStore());
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
cblHttpClientfactory.setSSLSocketFactory(context.getSocketFactory());
manager.setDefaultHttpClientFactory(cblHttpClientfactory);
} catch (CertificateException e) {
}
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
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!