How to configure wildfly to use https with ClientBuilder in resteasy? - java

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.

Related

How to download a binary large file throw HTTPS when the web server require a client TLS certificate?

I didn't find any way to implement an SSLContext with DownloadManager. Is there a way to add a Client certificate (keystore)?
For now, it is a self signed certificate (both client&server). I'm able to connect to this server with okhttp (managing SSLContext) but with DownloadManager i get an error 'SSL Handshake'.
Here is my code,
#Nullable
private static SSLContext initTrustManager(Context context) {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream is = context.getAssets().open("s_cert.cer");
Certificate ca;
try {
ca = certificateFactory.generateCertificate(is);
Log.i("TrustManager", "ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
is.close();
}
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
return sslContext;
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
And here is how I implement it:
builder.sslSocketFactory(initTrustManager(context).getSocketFactory());
This is working code, so if you still get exceptions, pay attention to SSL certificate itself or make some changes inside api of server. Hope it helps))

Trying to implement SSL on the Jersey client in order to talk to a secure server

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.

Android Https Connection with self signed certificate : hostName not verified

Hi I am testing Android connecion with certificate.
I have created a default ssl server on my ubuntu desktop. Enabled ssl and created the default self-signed certificate. I have then connected to https://localhost with firefox, added certificate to exceptions and then I used Firefox to save cerificate as .pem file.
I added certificate.pem to my android projetc in res/raw
I have gotten this code from android developer website to connect via https using my certificate (I don't want to trust everything I just want to verify if certicate is correct using the certificate in raw folder).
So when I connect I get:
java.lang.RuntimeException: java.io.IOException: Hostname '192.168.1.111' was not verified
Here is the class I use to verify the certificate
public class VerifyKey extends AsyncTask<Void, Void, Void>{
public static final String CERTIFICATE_TYPE_X_509 = "X.509";
public static final String CERTIFICATE_ALIAS = "user_desktop";
public static final String SERVER_URL = "https://192.168.1.111";
#Override
protected Void doInBackground(Void... params) {
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = null;
InputStream certificateInputStream = getApplicationContext().getResources().openRawResource(R.raw.user_desktop);
Certificate certificate = null;
try {
cf = CertificateFactory.getInstance(CERTIFICATE_TYPE_X_509);
certificate = cf.generateCertificate(certificateInputStream);
Log.d(TAG, "Certificate : " + certificate.toString());
Log.d(TAG, "Certificate public key : " + certificate.getPublicKey());
} catch (CertificateException e) {
throw new RuntimeException(e);
} finally {
if (certificateInputStream != null) {
try {
certificateInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance(keyStoreType);
if (keyStore != null) {
keyStore.load(null, null);
keyStore.setCertificateEntry(CERTIFICATE_ALIAS, certificate);
} else {
throw new RuntimeException("KeyStore is null");
}
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = null;
try {
tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
if (tmf != null) {
tmf.init(keyStore);
} else {
throw new RuntimeException("TrustManagerFactory is null");
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
}
// Create an SSLContext that uses our TrustManager
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
sslContext.init(null, trustManagers, null);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
}
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = null;
HttpsURLConnection httpsURLConnection =
null;
InputStream in = null;
try {
url = new URL(SERVER_URL);
Log.d(TAG, "URL : "+url.toString());
httpsURLConnection = (HttpsURLConnection)url.openConnection();
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
Log.d(TAG, "Socket factory : "+socketFactory.toString());
httpsURLConnection.setSSLSocketFactory(socketFactory);
in = httpsURLConnection.getInputStream(); //IOException exception gets triggered here
Toast.makeText(getApplicationContext(), in.toString(), Toast.LENGTH_SHORT).show();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (SSLHandshakeException e){
throw new RuntimeException(e);
} catch(UnknownHostException e){
throw new RuntimeException(e);
} catch (ConnectException e1){
throw new RuntimeException(e1);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
}
I have gotten this code from http://developer.android.com/training/articles/security-ssl.html#SelfSigned
I get this error on Samsung Galaxy s4 with Android 4.3
I don't have a lot of experience with HTTPS so here what I would like to achieve is povide certificate with the app which will allow to verify the server certificate.
Please if someone can suggest what I can modify in the code.
I also have a doubt because my server is a .local server but I connect using ip and the objective is to be able to connect using both ip a hostname, will that be problem when veryfying the hostname?
Thanks a lot in advance
EDIT: I have added code to get the hostname:
InetAddress addr = InetAddress.getByName(SERVER_URL);
String hostName = addr.getHostName();
I have tried using the hostname instead of ip but still I get the same exception:
Caused by: java.io.IOException: Hostname '<user.hostname.com>' was not verified
at libcore.net.http.HttpConnection.verifySecureSocketHostname(HttpConnection.java:223)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:446)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)
I have managed to solve the problem, it was actually a problem with the certificate:
sudo a2enmod ssl
sudo rm -rf /etc/apache2/ssl
sudo mkdir /etc/apache2/ssl
sudo openssl req -new -x509 -days 365 -nodes -out /etc/apache2/ssl/apache.pem -keyout /etc/apache2/ssl/apache.key
copy /etc/apache2/ssl/apache.pem somewhere else, change permissions of it to 777 (???)
and then add new apache.pem to res/raw folder of the app
then in common name field I have set the FQDN of my server such as host.name.com, I then updated the cerificate and key settings in /etc/apache2/sites-available/default-ssl
All this thanks to site https://library.linode.com/web-servers/apache/ssl-guides/ubuntu-10.04-lucid

Self-signed certificate

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.

KeyStore loading causing EOFException error on Android

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.

Categories

Resources