Certificate Path validation in Java including CRL validation - java

I have an intermediate certificate chain, a root certificate and a client certificate. I have to verify that they form a valid certificate chain together. This is working great when I have one intermediate certificate with a valid CRLDistributionPoint entry. The Java CertPathValidator API handles the validation beautifully.
My question was about the scenario when there will be multiple intermediate certificates and each of them might have a CRLDistributionPoint entry. Do I need to write additional code to handle this case? Or will Java simply validate against all CRLs? Or is it that the root certificate can delegate CRL Signing to just one certificate?
I tried searching online and could not find any clues. In addition to the answer to my question, it'd be great if someone could point me to a resource about PKI and certificates in general. Thank you!

No, you do not have to add code, the JDK implementation can smoothly handle the validation of a certificate path containing more than one intermediate CA certificates.
Note that the validation code is also tested against the PKI Test Suite from the NIST. That test suite tries to provide a comprehensive list of certificate and certificate path validation test cases.
If you want to look at the implementation code, you can look at the OpenJDK implementation : http://www.docjar.com/docs/api/sun/security/provider/certpath/package-index.html

Related

Jboss EAP 7 - Dynamic SSL authentication for REST API clients

I'm trying to get my head around some questions about SSL certificates and their signing.
My need : I need to be able to add (generate?) client certificate to allow them to use my API.
My problem : It seems that Wildfly needs to be reload if the java truststore is changed in order for the modifications to be available.
What I understood : This is a wrong approach of the problem and what should be done is the following:
Get a CA certificate from a trusted authority
Add this certificate to my keystore
Use that certificate to sign the clients certificates
This way only my CA certificate needs to be on my java keystores and through the CA validation chain, my client would be allowed on my service.
Questions :
Did I got this right ?
If I'm supposed to sign my clients certificates, what are they supposed to send me for the signing to be possible ?
Can this be done without calling keytool utility ? I'd like as possible can be to use java to do this and not rely on the OS.
If my CA certificate comes from a trusted authority and I use it to sign my clients certificates, those this still count as self-signed certificate ?
Thanks for all the pointers that you could provide.
Ok,
Since it may help others I'm going to put what my various testing helped me to figured out. :
Did I got this right ?
As far as I can tell : Yes
Why can't I be sure about it ? Because I'm encountering some testing limitations due to my development environment and the fact that I can't have a real valid certificate with a valid domain to test it.
If I'm supposed to sign my clients certificates, what are they supposed to send me for the signing to be possible ?
So what they need to send for the signing to be possible is a CSR (Certificate Signing Request) and their public key.
Can this be done without calling keytool utility ? I'd like as possible can be to use java to do this and not rely on the OS.
This should be doable using the Bouncycastle library. I'm using should because I did not go into implementing it, more on tha later.
If my CA certificate comes from a trusted authority and I use it to sign my clients certificates, those this still count as self-signed certificate ?
I'm still not clear on that, but it seems that there is some kind of scope on certificate signing that prevents anyone from faking the actual CA. Anyone that can put more sure knowledge on this, is welcome.
What I actually ended up doing :
Being our own CA would be too much hurdle, so what we're actually going to do is ask our clients to get their certificates from known CA and add those CA certs to our truststore. This is the same principle as before but instead of us playing at being CA, we'll leverage actual CA sources.
Hope this helps anyone that would some kind of equivalent requirement.

Use CA certificate my own code

I have searched on several topic but I don't really find what I need. The problem is : I'd like to sign file with digital certificate from my own writted program (desktop or web). Then I want to know:
If I can do that with CA certificate.
Which CA can issue me certificate I can use in my program. I mean CA certificate file with method to access to Algorithm, Key, and also to send verification request to server? A kind of API?
Does this kind of certificate exist ? Can I found it for free?
For as long as I understood your questions correctly, find below my answers:
1 - You can generate get you Digital Certificate by generating you key pair and then sign your public key by any CA (either your own CA or any Publicly trusted CA)
2 - You can make a request to a CA to get your Digital Certificate. Guessing that you want a publicly trusted certificate than you can use a wide range of CA's. I would suggest you to check the Let's Encrypt project, they release free certificates.
Using your digital certificate is a matter of your implementation. Basically you need to know what do you want to achieve with it (like confidentiality, authentication, integrity..). Usually you want to implement SSL to achieve any of these features.
For signing documents you need to encrypt with your private key associated with the public key that was used to get the digital certificate.
3 - As I also stated in the second answer, Yes there are free options for publicly trusted digital certificates

How to verify the incoming certificates from https with other certificates

Here I need to verify the SSL certificates for https websites with the root certificate. I have tried extremely lot but it could not be done yet. If anyone have any Idea to write such a code in java that could verify the Certs with the root cert. Mean that I have to check the certificate hierarchy signature validation for particular certs.
Thanks....
You need all root and sub root certs for validation. There is two different technologies; CLR and OCSP. OCSP is new one but some certificates support it.
You need some basic check for validate certifcate (also there are more rules):
Date is valid,
Certificate has ssl encription support, domain, etc,
Certificate issuer is correct,
Certifate rewoked or cancalled (with CRL or OCSP)
Java has own library for this, example: How to get server certificate chain then verify it's valid and trusted in Java

How to get CertPathValidatorResult in checkServerTrusted() of TrustManager?

When the checkServerTrusted method of classes implementing X509TrustManager is invoked, I need to get ALL validation errors that are associated with a certificate chain including
Certificate path validation problems. e.g CA not trusted
Certificate fields validation problems. e.g Expired certificate, Invalid extended key usage
The motivation behind this is so that I can present the user with the certificate validation issues before he adds it as an "exception" as Firefox does now. However, right now, as soon as a path validation issue is found, a CertPathValidatorException is thrown, but it gives me no information about the validity of the fields in the certificate. How can I implement this?
After some reading, I found the CertPath API provides such features, and found that the PKIX implementation is a wrapper around this, but just does not return the CertPathValidatorResult. I would like to make maximum use of existing JAVA functionality(without writing my own custom wrapper to the API) while returning all validation issues.
You won't even get to X509TrustManager.checkServerTrusted() if there was a certificate error. You would need to hook the certificate handling at an earlier point, and I don't believe there is one in JSSE.

A straight forward way to open self-signed HTTPS SSL URLs in java?

I'm building an application that needs to open self-signed HTTPS SSL URLs in java. I've learned that you can bypass the SSL problems by adding a call to HttpsURLConnection.setDefaultHostnameVerifier() where you say what hostnames are allowed.
However, I have a second problem where my servers are running self-signed certs. So even with the hostname bypass I'm getting exceptions like:
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've looked around and the only solutions I've found is to add the certificate to the java key store, but this is a problem for me because I have no control over when or how they update java, and I've read that the keystore isn't preserved between updates, and I have no access to the system outside of the JVM.
My application will only make calls to a single server so if there was a way to bypass the self-signed restrictions, and never consult keystores, it wouldn't be a security problem, but is there a way to do this?
I'm building an application that needs to open self-signed HTTPS SSL
URLs in java. I've learned that you can bypass the SSL problems by
adding a call to HttpsURLConnection.setDefaultHostnameVerifier() where
you say what hostnames are allowed.
There are some misconceptions from your question:
Hostname verification is unrelated to whether the certificate is self-signed or not.
It is a verification that matches the domain you are trying to access with the certificate info (CN or Subject Alt Name).
You would need to configure the verifier if you needed to accept a certificate that did not match the url (not recommended at all!!!)
Concerning the self-signed.
This is irrelevant.
You can configure your application to load your custom truststore which would include the certificate your application will trust. In fact this is the best approach (than using Java's cacerts).
All you have to do is import the certificate in a keystore (JKS or PKCS12) and load it in your custom TrustManagers in your application.
Just google arround, plenty of examples E.g. self-signed-ssl
As much as I hate to say this, sometimes it's better to just go with the flow.
Java is attempting to make applications more secure through the use of proper SSL verification practices. In this case, it is succeeding: had you been able to tell the program "it's okay, accept the untrusted self-signed certificate", your program would have been vulnerable to a man-in-the-middle attack where Mallory puts his server (with its own self-signed certificate, just as valid as yours!) in between the host and the target it's attempting to communicate with. Then he proceeds to read all the traffic you thought was nice and safe, and you don't even notice.
So, your assertion that telling Java to "trust any self-signed certificate when connecting to this host" is secure is, regrettably, not correct.
You can get free, totally valid SSL certificates from StartSSL. They're good folks.
That's how PKI is supposed to work - you must have complete chain of trust from some trusted certificate stored in you keystore to your certificate. So you can
set you certificate as trusted
ask somebody already trusted (i.e. with trusted certificate in the keystore) to sign you certificate
Trying to bypass that is not good bad idea. You can install you certificate in some Java post-install hook, you may have some cron job checking it periodically or do it in exception handling. You can even download this way a certificate from the server and install it everytime it changes (extracting the cert with openssl is easy). But for god's sake, if you decide to do such thing, at least write some audit log about it to some third machine a make sure somebody reads it.
You can also write "hacker-friendly" on you doors. :)
(Note that when you're talking about "keystore" in your question, you're in fact talking about the trust store (which is a keystore). More details on this unfortunately confusing Java terminology are in this answer.)
My application will only make calls to a single server so if there was
a way to bypass the self-signed restrictions, and never consult
keystores, it wouldn't be a security problem, but is there a way to do
this?
Actually, it would be a security problem. Your application may indeed be intended to call only a single server, but the trust store is precisely there to help make sure you're connecting to the machine you intended to connect to. Without it, you wouldn't be able to know whether you're connecting to that server or a MITM server.
If you want the security provided by SSL/TLS, don't bypass these rules. (In particular, don't use a trust manager that will accept any certificate.)
I've looked around and the only solutions I've found is to add the
certificate to the java key store, but this is a problem for me
because I have no control over when or how they update java, and I've
read that the keystore isn't preserved between updates, and I have no
access to the system outside of the JVM.
Quoting myself from this answer (to a more specific question):
The right way is to import this self-signed certificate into the client's trust store, using keytool for example:
keytool -import -file server-cert.pem -alias myserver -keystore mytruststore.jks
You can either do it directly in the JRE's trust store (lib/security/cacerts), which may lack some flexibility, or do it in your own copy of this file, which you then set as the trust store (the default password is changeit or changeme on OSX). You configure this truststore globally for your application using the usual javax.net.ssl.trustStore* system properties (e.g. -Djavax.net.ssl.trustStore=mytruststore system property (and -Djavax.net.ssl.trustStorePassword`). [...]
You don't actually have to use the trust store provided by the JRE (and which may be updated regularly). You could import your self-signed cert into a new empty keystore, which you'll use as a trust store within your application (don't import the private key with it). How to discuss trust store management was in fact discussed in this question: nothing prevents you from using a different trust store specifically for your application or part of it (and in fact Sun/Oracle make no guarantee as to the suitability of the default trust store).
I'm building an application that needs to open self-signed HTTPS SSL
URLs in java. I've learned that you can bypass the SSL problems by
adding a call to HttpsURLConnection.setDefaultHostnameVerifier() where
you say what hostnames are allowed.
While it may indeed by slightly less of a problem if you only have a single self-certificate in your trust store, host name verification is also an essential component of the security provided by SSL/TLS. Don't bypass it, verify that the certificate you're connecting to matches the name you're trying to connect to. (To make an analogy, if you want to check someone's identity, you not only want to check the their passport was emitted by a country whose passports you trust, but you'll also want to check they have the right name inside, otherwise you could be in front of anyone from that country.)
Making the CN= RDN of the Subject Distinguished Name of your self-signed certificate be the host name of the server should be enough, although it's the legacy way of doing it. You may also want to add the Subject Alternative Name extension. More on this in this answer.
Generally speaking do not bypass the SSL "problems". These mechanisms are precisely in place to make the usage of SSL/TLS secure.

Categories