Version en Español
This process comprises two stages:
1) Saving the server certificate in a keystore; and
2) Consuming the web service and indicating the location of the keystore with the certificate to the application.
In some cases, we also need to:
3) Setting up a client certificate (pfx) in the Java keystore
First, it must be made clear that, for communicating with an https resource, we must have installed the server certificate with which we seek communication. Such certificate contains the public key used to encrypt the information sent, only to be decoded by the server with its private key (read more here). So, at the time of consuming a service under https, we will need the server certificate in order to establish our communication.
After obtaining the certificate we must save it in a keystore. A keystore is "a store with certificates" allowing us to add new certificates or delete others, among other possibilities. A way to handle/manage keystores is by using the "Keytool.exe" tool in the JDK.
The above may be summarized into two simple steps:
With the IExplorer go to the server from which you want to obtain the certificate (https://www.dominio.com/webservice). Then go to File->Properties->Certificates. In 'Details' go to 'Copy to File...' and select, for instance, 'Base-64 encoded X.509'. By doing this you will be saving the certificate in a file.
1.2) Adding the certificate to a keystore
Add the certificate (ex) "certif.cer" in the keystore MiKeystore:
C:\>"c:\Program Files\Java\jdk1.5.0_05\bin\keytool.exe" -import -file certif.cer -keystore c:\MiKeystore -storepass MiPassword
After the steps described above, you must indicate the location of the keystore to the application so that, when the time comes to establish communication, it will know where to take the certificate from. To do this you must set up the system properties: javax.net.ssl.trustStore, and javax.net.ssl.trustStorePassword. It is usual to add the properties to the instance of the virtual machine. This may be done in the GX Interpreter Options in the case of a win application, or by adding these entries to the Java options of the Tomcat for the case of a web application (more details bellow).
You may otherwise set up by code, adding the following lines to the routine that consumes the service (or to any other part of the application executed prior to consuming the service):
java System.setProperty("javax.net.ssl.trustStore", "C:\\MiKeystore");
java System.setProperty("javax.net.ssl.trustStorePassword", "MiPassword");
The same steps apply in this case for saving the certificate, except that here, the trustore is not configured with our own keystore (Mykeystore). We must include it in the keystore of the tomcat located at %JAVA_HOME%\lib\security\cacerts
The following command is used for the inclusion:
keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>
For example:
C:\Program Files\Java\jre1.8.0_51\bin>keytool -import -noprompt -trustcacerts -alias fortigate -file C:\mykeystore\fortigateinf.cer -keystore ..\lib\security\cacerts
To list and verify that we have added the certificate, use the following sentence:
keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts -storepass changeit
NOTE: the default password for the keystore is changeit
Then we have to set up the trustore with that keystore, and to do it we have two options:
a. At the application level, by embedding the following in the GeneXus code:
java System.setProperty("javax.net.ssl.trustStore", "C:\\...\\jre\\lib\\security\\cacerts");
java System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
b. Or the option of adding the following properties to the Tomcat:
-Djavax.net.ssl.trustStore= %JAVA_HOME%\lib\security\cacerts
-Djavax.net.ssl.trustStorePassword=changeit
Afterwards we must restart the webserver (Tomcat)
IMPORTANT: In some cases we might get the following error when invoking the webservice:
javax.net.ssl.SSLException:
Connection has been shutdown:
avax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to findvalid certification path to requested target
Solution: This error occurs because after going over the whole hierarchy of .cer files, no reliable Certifying Authority was found. This means that the certificate was subscribed with an unreliable signature (meaning that it is not in the keystore). In such cases, view all certificates in the site and add them all to the keystore using a different alias for each case (option -alias of the option -import)
For example, if the certif.cer includes any reference to another certificate (Double Click with the .cer and then Certification Path, to get a tree with several certificates). You must download each of such certificates (.cer) and execute a keytool. command similar to the previous one, by changing the alias for each file. It would be something like this:
keytool -import -noprompt -trustcacerts -alias certif2 -file certif2.cer -keystore "C:\Program Files (x86)\Java\jre1.8.0_91\lib\security\cacerts" -storepass changeit
There are cases where we need to send a certificate from the client, including a private key (.pfx). In such cases we must do the following:
keytool.exe -importkeystore -destkeystore <nombreKeyStore> -srckeystore <ruta archivo pfx>\archivo.pfx -srcstoretype pkcs12 -deststoretype JKS -srcstorepass <password>
When the certificate password complies with the minimum security rules (like having more than six digits), we may create the new keystore with the same password that corresponds to the certificate. Otherwise, we will have to change the password of the client certificate so that it matches that of the KeyStore.
In order to change the certificate password:
- Get the alias of the certificate:
keytool.exe -list -v -keystore <nombreKeyStore>
- Change the password doing the following:
keytool.exe -keypasswd -alias <alias> -keystore <nombreKeyStore>
To this end, we have two options:
a. At the application level, by embedding the following in the GeneXus code
java System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
java System.setProperty("javax.net.ssl.keyStore", "C:\\ClientCertificate\\cacerts2");
java System.setProperty("javax.net.ssl.keyStorePassword", "Password");
b. To add the following properties in the Tomcat:
-Dsun.security.ssl.allowUnsafeRenegotiation=true
-Djavax.net.ssl.keyStore=C:\ClientCertificate\cacerts2
-Djavax.net.ssl.keyStorePassword=changeit2
-Djavax.net.ssl.keyStoreType=JKS
Use the Location data type to set all parameters for the service if you need to change them in runtime, for example:
// Set the trust store parameters on the Application server or use Java properties
java System.setProperty("javax.net.ssl.trustStore","..."); // for example C:\\Program Files (x86)\\Java\\jre6\\file
java System.setProperty("javax.net.ssl.trustStorePassword","xxxxxx"); // set correct password
// Location data type to change WebService parameters
&location = getlocation("WebServiceName")
&location.Host = "host"
&location.port = 443
&location.BaseUrl = "/WebAppBaseURL/servlet/"
&location.secure = 1
// WebService execution
&WebService.Execute(/*parameters*/)
In order to Debug, add the following properties :
-Djavax.net.debug=ssl:keymanager