Importing SSL certificates on the Java Keystore (JKS)
The mechanism usually adopted for the protection of end-to-end data on the Internet is based on the use of Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), both of which are cryptographic protocols that allow communication safer and integrity of data over TCP/IP, encrypt the communication from the source to the destination transport layer.
A typical TLS/SSL (for example via internet browser) provides an authentication type called unilateral: only the server is authenticated (the client knows the identity of the server), but not vice versa (the client remains anonymous and authenticated). The client (Web browser, EmailUI, Java Client, etc ...) validates the server certificate by checking the digital signature of server certificates, verifying that it is valid and recognized by a known Certificate Authority using a public key encryption.
Figure 1 illustrates the case where the browser establishes a connection to a website (or web application) that exposes a certificate from a Certificate Authority not recognized. The user can take certain actions, whether to continue or abandon the connection, it is also possible for the user, consider instructing your browser to trust the certificate.
Figure 2 shows the details are on the chain of certification (Certificate Chain). The browser (in this case Safari) has all the reasons to issue a warning, in effect, the Certificate Authority (CA) has indicated a pure invention.
If you'd like to make TLS/SSL connections using software written in Java (as a client), you must ensure that all Certificate Chain (or certificate chain) is satisfied or at least should have to trust the certificate . The Java platform uses a system called Java Keystore for the management of security or rather, storage and administration of all that revolves around digital certificates (Public/Private Key, Root CA, CSR, etc ...). The default implementation is based on the Java Keystore file, it is a proprietary format called JKS. For those wishing to know more about security in Java, I recommend reading JDK Security-related APIs & Developer Guides which will show you all the new features and improvements of JDK 8.
The Java platform provides two basic types of Java Keystore that I prefer to divide as follows:
- Server side: Java Keystore that usually contains the pairs of public/private key certificates used by the server. The name is usually attributed to this repository keystore;
- Client side: Java keystore containing the certificates that are used only by applications that act as a client. The name usually given to this repository and trustStore.
The default location of both the keystore is <java-home>/lib/security/. For simplicity, during the course of the article I will refer generically to keystore name.
The classic mistake that we encounter when the Certificate Chain is not met, is an exception of the type shown below. The exception is triggered because it was not found a valid Certification Path to the SSL connection request executed.
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Come on now in practice and see how to deal with a similar scenario taking as an example a recent article posted on my blog, which showed how to implement a SOAP Java client for SugarCRM system. Examples of connection (see article) to a SOAP service using the HTTP protocol. If we did use the HTTPS protocol to connect to a SOAP service, we would go meet the exception shown above. The solution is very simple, you must import the SSL certificate on your Java Keystore and mark it as trusted. The operation consists of the following elementary steps:
- Export/Save the server certificate in format DER (Distinguished Encoding Rules) or X.509 on your machine that will perform the SSL connection;
- Importing the server certificate on the Java Keystore.
Export the server certificate can be accomplished in several ways, perhaps the easiest way is through a common browser (Firefox, Internet Explore, Safari, etc ...). Publishing the post that explains how to do this with Mozilla Firefox: Exporting to File Server Certificate in Firefox 3. Similarly, you can proceed to export the server certificate using the most common browser.
The method that I prefer to export the server certificate in DER format is to use the openssl tool (see command below).
echo | openssl s_client -connect sugarcrm-fe-1.local:443 2>&1 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | openssl x509 -outform der -out /tmp/sugarcrm-fe-1.local.der
Once you have the server certificate, you must import it on the Java Keystore using the appropriate tool named keytool (keytool-Key and Certificate Management Tool). I remember that the keystore is the container of digital certificates. The scenario proposed here is based, custom keystore to a file, created from importing the server certificate, we leave intact the system keystore.
keytool -import -keystore /Users/amusarra/.mykeystore -alias sugarcrm-fe-1 -v -file Desktop/sugarcrm-fe-1.local
The command shown above, will create a new keystore (password protected) within the server certificate will be identified with the alias sugarcrm-fe-1. The alias uniquely identifies the item just inserted, if we wanted to do a check on the success of the operation of the import, just run the following command:
keytool -list -keystore /Users/amusarra/.mykeystore -v -alias sugarcrm-fe-1
The output of above command will look like as shown below:
Alias name: sugarcrm-fe-1 Creation date: May 2, 2011 Entry type: trustedCertEntry Owner: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local, OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com, OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT Serial number: 1 Valid from: Thu Apr 28 02:18:12 CEST 2011 until: Sun Apr 25 02:18:12 CEST 2021 Certificate fingerprints: MD5: CC:4A:D4:6E:DC:01:60:1D:79:FA:CD:8A:46:5F:CC:48 SHA1: A5:44:B9:C7:0A:41:0C:92:46:C6:9D:6D:77:0B:89:35:ED:E9:1C:AD Signature algorithm name: SHA1withRSA Version: 1
In the event that the server certificate was not imported successfully, the previous command would respond with the following exception:
keytool error: java.lang.Exception: Alias <sugarcrm-fe> does not exist java.lang.Exception: Alias <sugarcrm-fe> does not exist at sun.security.tools.KeyTool.doPrintEntry(KeyTool.java:1339) at sun.security.tools.KeyTool.doCommands(KeyTool.java:869) at sun.security.tools.KeyTool.run(KeyTool.java:172) at sun.security.tools.KeyTool.main(KeyTool.java:166)
At this point everything is ready to perform successfully connect to the service SOAP over HTTPS. Because we used a custom keystore instead of exploiting the system, you must instruct the JVM about the keystore to be used, not even a bad idea to set a debug level over the SSL connection. The two arguments that must be passed to the JVM are therefore:
-Djavax.net.debug=ssl -Djavax.net.ssl.trustStore=/Users/amusarra/.mykeystore
As the Java application acts as a client, you must specify the location of the keystore (remember to be kind trustStore) through the property java.net.ssl.trustStore.
The debug option can help you understand any problems in case of failure, it is useful for those who want to better understand the operation of the TLS / SSL, it draws all the messages exchanged between the client and the server to complete the handshake. Followed by an extract of the output against the execution of the class SugarCRMSoapClient.java but change the endpoint address at https://sugarcrm-fe-1.local/crm-6.1/service/v2/soap.php?wsdl
Through a practical example and I would also realistic enough, we saw how simple and immediate import digital certificates in the Java Keystore, so that applications work correctly.
I think this is my third article created to respond to questions or problems raised by my colleagues!
keyStore type is : jks keyStore provider is : init keystore init keymanager of type SunX509 trustStore is: /Users/amusarra/.mykeystore trustStore type is : jks trustStore provider is : init truststore adding as trusted cert: Subject: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local, OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com, OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT Algorithm: RSA; Serial number: 0x1 Valid from Thu Apr 28 02:18:12 CEST 2011 until Sun Apr 25 02:18:12 CEST 2021 trigger seeding of SecureRandom done seeding SecureRandom
*** ClientHello, TLSv1 RandomCookie: GMT: 1287446936 bytes = { 34, 19, 132, 181, 138, 114, 13, 67, 100, 111, 100, 155, 35, 132, 108, 102, 110, 106, 128, 57, 200, 147, 175, 25, 246, 233, 34, 252 } Session ID: {} Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV] Compression Methods: { 0 } *** Thread-2, WRITE: TLSv1 Handshake, length = 81 Thread-2, WRITE: SSLv2 client hello message, length = 110 Thread-2, READ: TLSv1 Handshake, length = 81 *** ServerHello, TLSv1 RandomCookie: GMT: 1287126586 bytes = { 72, 54, 32, 71, 9, 157, 75, 184, 3, 159, 95, 8, 18, 248, 108, 249, 179, 60, 205, 184, 204, 135, 186, 220, 27, 85, 249, 234 } Session ID: {116, 147, 251, 240, 232, 125, 76, 210, 112, 151, 13, 181, 7, 214, 55, 176, 224, 217, 109, 201, 161, 74, 143, 121, 131, 243, 108, 67, 131, 234, 146, 232} Cipher Suite: SSL_RSA_WITH_RC4_128_MD5 Compression Method: 0 Extension renegotiation_info, renegotiated_connection: <empty> *** %% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5] ** SSL_RSA_WITH_RC4_128_MD5 Thread-2, READ: TLSv1 Handshake, length = 1484 *** Certificate chain chain [0] = [ [ Version: V1 Subject: EMAILADDRESS=info@sugarcrm-fe-1.local, CN=sugarcrm-fe-1.local, OU=Research Development, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5 Key: Sun RSA public key, 4096 bits modulus: 8027142309184580181165847677029426633214754078003759815426876 85293215600656132119778686073861448440626986882469379232984072851534463520 18325441288568133145387170109806353233631082021605339971510561262203242740 78307947239417239633029107273682201967984685272509448411609722527933446350 55918234578745856629515337728940982589703027293942988170613441271688911660 69762683263953403322683456690226470741799474704382776226873825494609402390 72693542287588215034771548006899103813169868373935038762384493733844944158 52659434703986779316888612522163711433463948775434712084653698002329763637 public exponent: 65537 Validity: [From: Thu Apr 28 02:18:12 CEST 2011, To: Sun Apr 25 02:18:12 CEST 2021] Issuer: EMAILADDRESS=info@shiruslabs.com, CN=www.shiruslabs.com, OU=IT Systems, O=Shirus Labs Ltd, L=Rome, ST=Italy, C=IT SerialNumber: [ 01] ]