I use a hosting with a self-signed certificate. So I downloaded the certificate from my domain https://www.marpel.cz/ and created .bks file using http://portecle.sourceforge.net/.
I need to establish the https connection and retrieve data from my webservice. I use ksoap2 library. I have copied and used a class ConnectionWithSelfSignedCertificate stated in ksoap2 wiki.
This is the way I create a keyStore
MainActivity.java
// Get an instance of the Bouncy Castle KeyStore format
try {
this.keyStore = KeyStore.getInstance("BKS");
} catch (KeyStoreException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = this.getApplicationContext().getResources().openRawResource(R.raw.myCer);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
this.keyStore.load(in, "myPass".toCharArray());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
this.sslSocketFactory = new ConnectionWithSelfSignedCertificate(this.keyStore).getSSLSocketFactory();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And this is a code from AsyncTask
background task
final HttpsTransportSE transportSE = new HttpsTransportSE(URL, PORT, SERVICE, TIMEOUT);
try {
((HttpsServiceConnectionSE) transportSE.getServiceConnection()).setSSLSocketFactory(this.sslSocketFactory);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
If I call transportSE.call(SOAP_ACTION, envelope); I get IOException, Hostname 'www.marpel.cz' was not verified. What do I do wrong?
I have an ICS 4.1.2 device.
Firstly, do you use self signed certificate?
If yes, then follow this link: android-webservices-via-ksoap2-https
You need extra classes for creating https connection and accepting of the certificate. When everything is prepared, you can call your transportSE.
The code in my first post works fine. I have found out that the self-signed certificate was issued for different domain. I fixed the certificate and everything works fine.
The fixed certificate runs here https://www.marpel.cz:445/
Thank you, Martin.
Related
This is the first time ever I got the requirement to connect to https url. Within no time, I came to know that I need SSLContext to be passed.
I also came to know that I need to configure in standalone.xml to get it done.
Any pointers towards the solution/link, working code would be much appreciated.
Do we have to generate keystores ourselves? or wildfly provides any existing ones?
This is what I've tried:
SSLContext context = null;
KeyManagerFactory kmf = null;
KeyStore ks = null;
char[] storepass = "somestringhere".toCharArray();
char[] keypass = "somestringhere".toCharArray();
try {
context = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
try {
kmf = KeyManagerFactory.getInstance("SunX509");
} catch (NoSuchAlgorithmException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
FileInputStream fin = null;
try {
fin = new FileInputStream("file here");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
ks = KeyStore.getInstance("JKS");
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
ks.load(fin, storepass);
} catch (NoSuchAlgorithmException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (CertificateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
kmf.init(ks, keypass);
} catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
context.init(kmf.getKeyManagers(), null, null);
} catch (KeyManagementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Client client = ClientBuilder.newBuilder().sslContext(context).build();
WebTarget target = client
.target("https://....");
Builder builder = target.request();
I tried https://stackoverflow.com, it gave 200OK, I tried google.com, it said document has moved 302 status. I tried the url which I want to connect I got peer not authenticated exception
Caused by: javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:421) [jsse.jar:1.7.0_71]
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:128) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:572) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:640) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906) [httpclient-4.2.5.jar:4.2.5]
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805) [httpclient-4.2.5.jar:4.2.5]
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:283) [resteasy-client-3.0.6.Final.jar:]
... 30 more
And the server asks for basic authentication, is it the reason for the exception?
Here are my codes to use JAX-RS with HTTPS using Wildly 10.Note that Wildly implementation for JAX-RS is RestEasy 3.xxxx.
ClientBuilder builder = ClientBuilder.newBuilder();
builder.sslContext(ConnectionFactory.getSslContext());
builder.hostnameVerifier(ConnectionFactory.getHostnameVerifier());
client = builder.build();
String baseURI = acsUser.getSelectedService().getWebserviceBaseUrl();
WebTarget webTarget = client.target(baseURI);
Here is the class called ConnectionFactory.
public class ConnectionFactory {
Proxy proxy;
String proxyHost;
Integer proxyPort;
public boolean canConnect = true;
private static final Logger log = Logger.getLogger("ReportPortal");
public ConnectionFactory() {
}
/**
*
* #return
*/
public static SSLContext getSslContext() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new SecureTrustManager()}, new SecureRandom());
}
catch (NoSuchAlgorithmException | KeyManagementException ex) {
log.error("ERROR OCCURS", ex);
}
return sslContext;
}
/**
*
* #return
*/
public static HostnameVerifier getHostnameVerifier() {
return (String hostname, javax.net.ssl.SSLSession sslSession) -> true;
}
public Boolean isHttps(String url) {
if (url.startsWith("https://")) {
return Boolean.TRUE;
}
else {
return Boolean.FALSE;
}
}
}
"Do we have to generate keystores ourselves?"
Yes. You need to generate one for the Server and a Trust store (which is just a key store, but we just call it a trust store to differentiate it).
See SSL setup guide in the Wildfly documentation. It will show you how to create a keystore and configure it with Wildfly. Just follow the section "Pure Java SSL-Setup using keytool"
Then you need to create the client keystore. You will export the certificate from the server store and import it into the client store.
How it works is that the Client needs to trust the server. And the way to do that is through the Server certificate. Now if the certificate is signed by from a well known CA, generally Java will already support this cert, and we dont need to configure the client. But since you are creating your own self signed cert, we need to configure the client to trust the server certificate by importing it into the trust-store.
You can see all the step for handling the certs/stores for both client and server here in this post. Scroll down to step 5. The three code snippets that begin with keytool are the commands to complete this task. The first creates the server store named tomcat-keystore.jks (but you can name it anything). The next snippet exports the certificate from the keystore, into a file name tomcat.crt (but you an name it anything). The third command will import the previous cert into a client-truststore.jks (but you can name it anything). You'll notice that you don't need to explicitly create the trust-store, it be will create implicitly when we do an import.
Once you have the server keystore, follow the instructions in the wildfly documentation linked above and configure the store with the server.
To configure the Client, see step 6 in the above linked answer. It configures the client with the trust-store we created. Everything in the code is standard Java and JAX-RS except for the configuration of the Basic auth, which is specific to Jersey.
I'm following the example atb the end of chapter 3 in Sunil Gulabani's Developing RESTful Web Services with Jersey 2.0" Here's the code:
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();
The error I get is:
SSLContextImpl is not initialized
I certainly do initialize SSLContext, but SSLContext behaves like a regular class and not like an interface. So, what is SSLContextImpl. Anyone have any ideas?
Thanks,
Rob
You have to call SSLContext.init() with appropriate parameters.
I am getting a HTTP response code 405 when I use HttpURLConnection to make a DELETE request:
public void makeDeleteRequest(String objtype,String objkey)
{
URL url=null;
String uri="http://localhost:8180/GoogleMapsLoadingTest/rest/GoogleMapsErp/";
HttpURLConnection conn=null;
try {
url=new URL(uri);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn=(HttpURLConnection) url.openConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
conn.setDoInput(true);
conn.setDoOutput(true);
try {
System.out.println(conn.getResponseCode());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
conn.setRequestMethod("DELETE");
} catch (ProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
How can I make this request?
The 405 status code means that your method (DELETE) is not allowed for the resource you specified; in this case, what looks like an entire REST endpoint directory. You should use DELETE on the specific item you want deleted; perhaps you forgot to actually use the method parameters when constructing the URL?
It would appear to be a problem with your server. I'm guessing nginx, but let me know if not.
Take a look here to see how to compile ngninx with HttpDavModule. There are other servers that have issues with this, but nginx doesn't have it by default.
If you're running Apache, check your module configurations to see if you're disallowing them or not. Here's a post about a previous solution. Unfortunately, this problem is typically specific to modules that have been installed. On a vanilla installation, however, you can often just allow for DELETE (see your config file, as well as the OP of that link)
I have to retrieve the file path of the content from gmail app.
I get content uri similar to:
content://gmail-ls/messages/mymailid%40gmail.com/4/attachments/0.1/BEST/false
I tried queried for the contents but I get only two columns the title and the size. I want to get the file path.
Kindly help regarding this.
I think you cannot retrieve the file path directly, as the attachment is stored on Google servers. You can, however, access the file data using ContentResolver and InputStream, and copy the attachment's data to your storage.
Inspired by CarvingCode blog, I use this snippet:
if (intent.getScheme().compareTo("content")==0)
{
try
{
InputStream attachment = getContentResolver().openInputStream(data);
if (attachment == null)
Log.e("onCreate", "cannot access mail attachment");
else
{
FileOutputStream tmp = new FileOutputStream("/mnt/sdcard/attachment.pdf");
byte []buffer = new byte[1024];
while (attachment.read(buffer) > 0)
tmp.write(buffer);
tmp.close();
attachment.close();
}
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I have some code for my app that creates a keystore in android,
creates some default keys then saves the keystore.
Later on the code tries to reload the keystore, on the emulator this
runs fine however when run on a phone I get an EOFException. Any
advice on where I'm going wrong?
An out take of the code is below:
In the class I have the following variables
static KeyStore keyStore;
String filenameKeyStore = "KeyStore.kstore";
Then the following two functions
public KeyHandler(Context context) {
if(keyStore == null) {
Log.d("KeyStore", "Keystore is null so loading");
if(initialiseKeyStore(context) == false) {
// KeyStore failed to initialise
Log.e("ERROR", "Store failed to initialise");
}
}
}
private boolean initialiseKeyStore(Context context) {
FileInputStream input = null;
try {
// Get an instance of KeyStore
keyStore = KeyStore.getInstance("BKS");
// Load the KeyStore file
try {
// Try and open the private key store
input = context.openFileInput(filenameKeyStore);
} catch (FileNotFoundException e) {
// If the file doesn't exist then create the file, a ECDH key and
store the key
Log.w("Warning","File does not exist, creating new file");
try {
// Load the default Key Store
keyStore.load(null, null);
// Create the file
FileOutputStream output =
context.openFileOutput(filenameKeyStore, 0);
// Reset private key
resetPrivateKey(context);
// Save the key
keyStore.store(output, "password".toCharArray());
// Close the keystore and set the input stream
output.close();
input = context.openFileInput(filenameKeyStore);
// Reset the keyStore
keyStore = KeyStore.getInstance("BKS");
} catch (FileNotFoundException ee) {
Log.e("ERROR", "File not found, even though we just created it");
return false;
} catch (NoSuchProviderException e1) {
// BC isn't working exit
e1.printStackTrace();
System.exit(1);
} catch (InvalidAlgorithmParameterException e1) {
Log.e("ERROR", "The algorithm used for secure algorithm is
incorrect");
e1.printStackTrace();
return false;
}
}
// Load the store
keyStore.load(input, "password".toCharArray());
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (EOFException e) {
// Where the exception is caught
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (NoSuchProviderException e) {
// Serious error, return
e.printStackTrace();
System.exit(1);
}
return true;
}
This usually happens when the keystore file is corrupted. We just had (again) such issue with a keystore sent by an external dev who was unable to recall how exactly did he created the keystore file.
Create a new keystore file and import the certificate(s) - this will solve the problem.