SSL trusted certificates in java - java

Do we need to explicitly import the Trusted CA Certificates into the java keystore? If so, then why?
I can understand that we should always import the Self-Signed SSL certificates into the keystore, because they are not verified ones and java can't trust unless it's there in the keystore. But do we need to exercise the same thing even for Trusted CA Production Certificates?
Note: I'm using jdk v1.6.x.

I can understand that we should always import the Self-Signed SSL certificates into the keystore, because they are not verified ones and java can't trust unless it's there in the keystore.
In the trust store.
But do we need to exercise the same thing even for Trusted CA Production Certificates?
No. If the CA is already trusted by the Java truststore you don't need to do anything.

It does not matter, if you use a self-signed certificate or a CA certificate. You need to import it into the truststore (which can be the same file as the keystore) to make it available to your java application. Java itself does not load any trusted certificate from the Internet because it does not know, which site it can trust, and which not.

Related

TLS Authentication between Servers and their Keystores Trustores

Before I go to the main question, I do want to state my understanding on Keystore and TrustStores:
1) Keystore - Details of key (private key) using which I would do my authentication as a server
2) Truststore - The list of root/interm CAs and other signed Certificates from different domains which I trust.
I am trying to establish an inter-server authentication and data exchange mechanism. All my servers has FQDN format as myserverX.mydomain.net where X is the index e.g. myserver1.mydomain.net. If my understanding on keystore and truststore is correct, when myserver1 is requesting data from myserver2, it's myserver1 who is client and myserver2 is server.
In this way:
1) myserver1 needs to trust myserver2 so myserver2 public key certificate should be imported into the truststore in `myserver1'.
2) The above will also be true when 'myserver1' is server and myserver2 is client - except now myserver1 public key certificate should be imported into myserver2 truststore.
Am I actually getting things right here? Or is there any fundamental mistake I am making? My intention was to try it out with self-signed certificate, and then, get a proper root CA signed certificate for my servers. But I would be grateful if someone can explain if I am making any wrong assumptions here.
Note - I am going to use Java keytool and JKS-type keystore (with default symmetric key algo and size) and I will use either -certreq and -gencert or -selfcert to generate a self signed certificate for my test.
You have it right but if you use CA-signed certificates the import step is not needed. CAs are already trusted, by definition, and therefore so are the certificates they sign. So your test is pointless.

Converted PFX SSL cert throwing SSLHandshakeException?

I was given a PFX "wildcard" SSL certificate (I believe its a VeriSign cert) for *.ourdomain.example.org. I then used this answer to help me convert the PFX into a JKS keystore entry and add it to a JKS keystore. When I run keytool -list -keystore mykeys.jks I see:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
<my key's long GUUID>, May 1, 2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): <cert's fingerprint>
So I know the converted PFX cert is in there. But at runtime, when JNDI is using SSL to establish a connection to my AD server (over LDAPS), I am seeing the following exception:
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
I'm wondering if something got botched in the conversion from PFX to JKS. I'm pretty sure nothing else is wrong with the SSL cert, because I was using a self-signed cert before using this PFX and my browser was giving me the typical "I do not trust this certificate" warning. After I added the converted PFX and restarted my app, those warnings went away. Any ideas as to what could be going on here?
Firstly, in many cases, you don't need to convert from PKCS#12 (PFX) to JKS, many applications will let you set the keystore type to PKCS12 (instead of the default JKS), which will allow you to use your PFX file directly.
It looks like you're mixing up the usage of trust store and key store here (see this question).
Having a keystore with a certificate and its PrivateKeyEntry (here, coming from a PKCS#12 file) is normally used as a "keystore keystore" (as opposed to a keystore used as a truststore). This would normally be used for the certificate you present to your clients as a server, or the client certificate you use when connecting to a server that requests one.
Here, the "PKIX path building failed" exceptions means that your Java application doesn't trust the remote certificate it is connecting to. Presumably, your AD server has nothing to do with this JKS keystore. Rather, your server that uses your keystore is also a client to that AD server, and it cannot trust the AD server certificate.
You don't say how you've configured your application. Perhaps you've used your keystore for both the keystore and truststore settings (effectively preventing the use of the CA certificates bundled with the default JRE truststore), or perhaps your AD certificate is self-signed or not issued by a CA that is part of the default truststore. If the latter is the case, simply import the AD certificate (just the certificate, not the certificate and its private key) into the trust store (you can either do this into the JRE's cacert file or make a copy of it and use that using the javax.net.ssl.trustStore and related system properties).

How can I trust a specific self-sign certificates? (Not trust all)

How can I set my HttpsURLConnection to trust a specific certificate only? Currently my code is set to trust all certificates. But the requirement is to trust only a specific certificate and do not trust the others. How can I do it in Java? I'm using JDK 1.5.
You can trust a specific certificate by creating a custom SSLSocketFactory and providing your own TrustManager. See...
Trusting all certificates using HttpClient over HTTPS
and
How can I use different certificates on specific connections?
In your TrustManager, you will be handed the certificate chain from the client / server to verify against your specific certificate.
Import it into your client truststore.

How to add fingerprint to keystore

I had the following exception while writing to a SSL socket
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
It seems like the certificate of the target server is not trusted. I tested my implementation on a windows 7 machine, jdk7 and tomcat7 with no problem. The Exception is thrown on ubuntu 10 LTS with openJDK 6 and tomcat7. I got the sha1 and md5 fingerprint of the sockets target server. Am I right that the certificat of the server I am trying to stream to is not trustet on my ubuntu server? can I can the fingerprint to the tomcats keystore? If so, how do I do this?
It's not the fingerprint that you need to add to your trust store, but the actual certificate.
You can add the server certificate itself or add one of the CA certificates in the chain (if you wish to trust the all the certificates from that CA, not just that particular server).
To find out what the certificate is, you can use OpenSSL:
openssl s_client -showcerts -connect your.host.name:443
(Replace the host name and 443 by the actual ports you're using.)
The blocks between --BEGIN/END CERT...-- are the certificates in PEM format. You can check their content using openssl x509 -text -noout (and pasting each block there).
Save the certificate you want to import into a plain text file (e.g. certificate.pem). You should only import certificates that you trust. There's a certain leap of faith here. (You might want to connect with your browser and check whether the key material matches, for example.)
To import into your truststore use:
keytool -importcert -keystore truststore.jks -file certificate.pem
(You may need to specify an alias wit -alias some_name_you_choose.)
If you want this to affect your default truststore, replace truststore.jks with the path to lib/security/cacerts in your Java home directory (the default password should be changeit).
Since the target server seems to come from a well-known CA anyway (and it works with some versions of the JRE), the easiest fix is certainly to update your cacerts file manually, taking a copy from a JRE with which it works. After all, as the JSSE Reference Guide says:
IMPORTANT NOTE: The JDK ships with a limited number of trusted root
certificates in the /lib/security/cacerts file. As
documented in keytool, it is your responsibility to maintain (that is,
add/remove) the certificates contained in this file if you use this
file as a truststore.
Depending on the certificate configuration of the servers you contact,
you may need to add additional root certificate(s). Obtain the needed
specific root certificate(s) from the appropriate vendor.
It turns out it's certainly a problem with the certificate chain order (which is incorrect on this site), as shown by Qualys SSL Labs tester.

using spring-ldap with ssl

I need to talk to an LDAP server via spring-ldap with SSL, and the other end has a self-signed certificate no less.
Can any kind soul please point me to some instructions for setting this up?
Check out Spring LDAP documentation for connecting to LDAP server over HTTP(S):
As far as self signed certificate is concerned, you can import certificate chain into a truststore and set the following VM arguments:
-Djavax.net.ssl.trustStore="<path to truststore file>"
-Djavax.net.ssl.trustStorePassword="<passphrase for truststore>"
or override the truststore at runtime like:
System.setProperty("javax.net.ssl.trustStore","<path to truststore file>");
System.setProperty("javax.net.ssl.trustStorePassword","<passphrase for truststore>");
Keep in mind that both options will override default JVM truststore. So if you are hitting different sites with different certs, you may want to import all of them into one truststore.
In case you need help creating truststore file, refer to this: Digital Certificate: How to import .cer file in to .truststore file using?
Note: If the other end is a trusted source then you might also skip the certification check, as I had to do because any few months the certificate was changed and I was constrained to import into my local truststore and the other environments' truststores, test, production, the new certificate, every single time.

Categories