I'm currently building a .NET webapi service that is supposed to be used by IBM Notes. The connection in the final product is supposed to be a call from a domino server to the webapi using a java agent over https.
Up until now I've been using http communication between the two, easy enough.
But now I wanted move to https instead, so I created a self-signed certificate and inserted it into IIS using a guide from Jayway.com from Elizabeth Andrews.
After some tweaking I got it working and my self signed certificate is trusted by the os.
The cert is:
SHA512 RSA2048bit
I found this "guide" on how to insert the certificate into the cacerts store in notes:
http://www-01.ibm.com/support/docview.wss?uid=swg21588966
although working on the client and this guide is for server a assumed the jvm would work the same on both.
After this i tried a simple https call inside a java agent in the fashion shown here:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/Connecting_to_a_Domino_server_over_SSL_in_Java_using_a_self_signed_certificate._
Now my problem is that the code works when run as a java project, but when running the code as a notes agent I get this exception:
javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.j: No trusted certificate found
If there is anyone who would like to nudge me in the right direction i would be very grateful.
Your Domino server has a directory called names.nsf in which it stores (inter alias) the credentials it trusts. This natively includes the root certificates of the major certificate vendors such as Verisign & co.
Two options here :
- go pro and buy a certificate from a well-known vendor
- or import your own self-signed certificate in the Domino repository.
Related
I have a client/server application that sends data over SSLSockets, so I generated a cert and loaded it with a trust store and keystore. The client is going to be public, so in order to work I need the client to have the javaTrustStore.jts file with it. Is it ok to bundle it in the resources directory? Or should I have the client generate a new key every time and add it to the server's keystore?
There are two ways that you can approach this.
The first is to have a certificate just on the server, and no certificate on the client.
The is the usual way that websites work - when the SSL connection is negotiated, the server sends it's certificate to the client, and the client verifies that the server cert is signed by a Certificate Authority that the client trusts. Most (all?) web browsers are pre-loaded with a number of certificate authoritys' "master certificates",
So, a Java application operating in this mode would need the "master CA certificate", and any "intermediate" signing certificates in it's trust store.
You can also be your own CA, which was done often in years past, when you had to pay for a server cert. These days, if you want a free cert, you can just use Let's Encrypt, or one of several other providers of free certificates.
If you need to validate the client when negotiating the SSL connection, then you would also put a certificate on the client. But, you can't just have the client generate it's own certificate. You'll need to have your CA generate and sign the certificate, and then give that to the client, who would need to add it to their keystore.
Again, in this case, you can act as your own CA, and generate "self-signed" certificates.
If you'd like to see an example of this, I wrote a blog post for my employer's web site about nine or ten years ago about doing this with an Android app.
I've got an Android App trying to send HTTPS Requests to a server having a Symantec Class 3 Secure Server CA - G4 signed certificate.
When trying to send a request via the apache http library (I guess this is also true for other HTTP clients) an exception stating "No peer certificate" is thrown. The same requests to the same servers on iOS work fine and even if I connect to the server in chrome, running on the same Android device I'm testing on, it says the certificate is perfectly fine.
Now I heard that Google dropped trust for some Symantec certificates, but as far as I know only the ones with a 1024 bit key. The one in question is signed with a 2048 bit key. And Chrome also accepts it!
I also found this article [1] saying that I need to import the complete keychain as BouncyCastle keystore. The problem here is, that every user specifies the url to their own server, managing their own certificates.
So my question is: Is anybody familiar with this problem and knows a workaround? I found endless of guides showing me how to turn of certificate validation for a request ... but that won't be a solution working for me.
[1] http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/
The problem I actually had was that the server required SNI (Server Name Indication) support on the HTTP client. Androids version of the apache http library does not support SNI. So I had to write my own SSLSocketFactory supporting it.
In a Java desktop application I need to connect to a SSL URL. When I try it, I get the exception:
SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
To solve it, I go to the address with my browser, download the certificate in .cert file and import in my java cacerts keystore using keytool command. After this, the application works fine.
My question is: why java don't recognize the certificate if this is signed with VeriSign? VeriSign certificate is not installed in cacerts keystore by default?
Maybe I don't understand how SSL works. What's the difference between browser and java desktop behavior? I can connect to this URL with my browser without installing nothing.
Thanks
When we access a secure site which uses SSL for providing identity and encryption, it provides a certificates which was verified by a trusted third party sites like verisign, godaddy or thwate.
By using certificates browser or java clients knows that they talking to the correct site (who it claims to be) and not on redirected proxy site. this step is pretty transparent if you access websites using browser because if certificate is not on browser's trusted store it will ask you to add that certificate and it will be subsequently added.
But when you access a secure site using Java program, this step of certificate hand shaking is not transparent to user and certificates are verified form JRE's trustStore.
Read more: http://javarevisited.blogspot.com/2012/03/add-list-certficates-java-keystore.html#ixzz32v1wL3Gl
You did not say which certificate you imported into the keystore. Usually there are several certificates involved in the verification:
the trusted root certificate, which is stored in the keystore or browser (Java does not share the keystore with the browser)
the leaf certificate which identifies the site
and most times also intermediate certificates, which provide a signed way from the leaf certificate to the trusted root and thus establish a trusted path
If any of the intermediate certificates is missing, the verification fails.
So the server has to send not only the leaf certificate, but all intermediate certificates too. And this is where lots of sites fail, e.g. they don't provide the full certificate chain.
But why does this work in the browser?
Because enough sites fail to provide the intermediate certificates and because the browser wants to provide the best experience, they will cache the intermediate certificates. Thus, if you go to one site signed by verisign which provides the trusted chain, and then go to another site signed with the same certificate, but which does not provide the chain, then it will still work, because the chain certificates are cached from the other side.
But, if you use a fresh system (or simply a new browser profile with firefox) and visit the misconfigured site first, it will complain there too, as much as the Java application did. And if you just import the relevant intermediate certificate into the keystore and thus trust it it will work too, because it does not need the rest of the chain to get a path to a trusted certificate.
I've read a lot of articles regarding the import of a cert, but I am still unclear on a couple things.
When connecting to an SSL site from a Java application [in this case, a JBOSS web app], does the client cert need to be explicitly installed on the application server prior?
I can install a client cert manually, but there is an expiration date. So I'll need to manage the expiration dates of all client installed certs on our application server, and take an outage to update each one.
It feels like there should be a better way.
Shouldn't the application automatically accept a valid signed cert? [In this case, it is signed by VeriSign]
We are getting an exception currently when trying to access an https url from the application without explicitly installing the cert.
The API proxy library is swallowing the internal exception, so I dont know the details.
If the cert should be accepted automatically, then there may be a different issue here...
Can a signed certificate be used without importing explicitly?
Yes, it does not need to be installed prior to use. In fact, if you know in advance of what to expect, then you can include that information into the application. That has an added benefit of improving the application's security posture.
To avoid importing the certificate, use a custom X509TrustManager and override checkServerTrusted. In checkServerTrusted, ensure the server's public key is expected (i.e., pin the server's certificate or public key); or verify the server's certificate is valid (i.e., is within validity and forms a chain to your trusted root).
When connecting to an SSL site from a Java application [in this case, a JBOSS web app], does the client cert need to be explicitly installed on the application server prior?
In the case of client certificates, the server advertises the issuer whom it relies upon to issue client certificates. So the server will need to know the trust point for issuing client certifcates for authenticating clients.
In this case, it is signed by VeriSign
This could be really bad. In this case, you will trust all of your clients signed under the Verisign PKI, and all of Verisign's other clients signed under the Verisign PKI.
In this case, it would probably be better to avoid public CAs and run your own PKI (i.e., be your own CA). In this case, pick up a copy of Network Security with OpenSSL. The book will show you how to accomplish the customary tasks using both the openssl command and programmatically.
I have a swing application deployed in HTTP Server. Users use the browser to point an URL and install the client using java webstart. Now I need to enable https access to my application deployed on HTTP server. I am using JDK 1.5 as default jdk supported in the jnlp file. For time being I use a self signed certificate to the sign the jars (by default created using Sun's jarsigner, keytool, etc, utils).
Solution/steps would be much appreciated.
Thanks in advance
Ramesh
As far as I understand your question you don't need to change anything to your code of the client. If you only want to give access to the JNLP via HTTPS you would only need to reconfigure the application server distributing the JNLP or if you have a webserver in front of the application server (as we do here: user - https -> apache -> AJP -> tomcat) you need to reconfigure the webserver to allow the access to the JNLP via HTTPS.
You need to enable HTTPS on the web server. To get the certificate you need to provide credentials and the host name of the server to a certificate authority (CA) like VeriSign or Thawte. They can provide you with a server certificate signed by their root certificate or some intermediate certificate. This certificate must then be imported into the web server to enable HTTPS over SSL. The web clients, like a browser or webstart will then verify the certificate chain when accessing the server.
If you use a self signed jar, all your users will be presented with a warning message about potentially unsafe code. To avoid this you should get a code signing certificate from a CA, which would be somewhat similar to the web server certificate. This CA-provided certificate can be imported into the keystore and used in the same way you use the self signed certificate. The code signing certificate will be signed by the CA so that the certificate chain can be verified by webstart.
What is the feature of https that you are hoping to leverage?
The signing/server authentication is done by code signing, though you are undermining this using a self-signed certificate.
Does your application code contain secrets that must be hidden from eavesdroppers?
As you say you "need to enable" there must be an underlying reason.
I believe that before you "need https" you need a proper code signing certificate. You might want to rephrase your question so that your underlying problem can be solved instead of the very specific question.