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
Related
I have a Java program that connects to an https remote webservice which exposes a TLS certificate of this structure:
Webservice certificate
Signed with some certificate
Signed with some corporate certificate
Now, when my Java app makes a https request to that webservice it fails due to invalid certificate. This is normal, so I added the webservice direct certificate to the Java/lib/security/cacerts file.
But this didn't work, I still had the certificate exception.
After a long debugging session and hours wasted, I tried to add all three individual certificates, and this time it worked. But why ?
Why does Java checks the full certificate path even though the direct certificate is made trusted ?
Is this behavior as per SSL/TLS RFCs ? Will this behavior occur with other tools/languages like curl ?
Thanks.
... so I added the webservice direct certificate to the Java/lib/security/cacerts file
The webservice certificate is not a CA certificate, so it does not belong in cacerts in the first place (as the name indicates). A CA certificate is a certificate which is used to sign other certificates, a webservice certificate is a leaf certificate which cannot be used to sign other certificates.
Will this behavior occur with other tools/languages like curl ?
This is a common behavior. With OpenSSL based tools one usually needs to provide the root CA (and of course the chain to it), only with X509_V_FLAG_PARTIAL_CHAIN it will accept when parts of the chain a specified as trusted.
My application is running in intranet in tomcat server. I am able to run my application with https but with warning(The security certificate presented by this website was not issued by a trusted certificate authority) also https symbol is crossed in red.
How we can have trusted SSL with self sign certificate in tomcat server without pain of importing certificate in browser?
How we can have trusted SSL with self sign certificate in tomcat server without pain of importing certificate in browser?
You can't. Self-signed is not trusted by default (where should the trust come from?) and thus you cannot expect the browser to trust it without telling the browser that it can trust it (by importing). Trust is a relationship and can not simply emerge from nowhere.
The warning States that the certificate is valid but browser don't trust the authority issuing the certificate. The only way is to Configure Browser to Ignore the untrusted CA issues, or Trust The organization in this case you .
Alternatively the recommended way is to get a certificate issues from one the of the CA Authority ( Verisign , Godaddy etc).
Any browser confirms below list items before marking a website/url secure:
Match the base DNS with that of the certificate CN (Note that the port number doesn't come into picture in this case). For example, if you are accessing https://example.com:8445/something, the certificate CN should be "example.com"
The self-signed certificate has to be imported into the respective trust store (Root Certification Authorities) of the system.
The certificate must have a SAN (Subject Alternative Name), that matches the DNS. With respect to previous example, the certificate must have at least one SAN equivalent to "example.com". This is a must, and most of the folks miss out on this point, and could not understand why the browser doesn't trust the certificate.
The Free way to establish trust in browser for internal applications
Now, all the above 3 criteria cannot be met unless the certificate is signed by a CA. However, there is an easy way. Go to https://freesslcert.org/ to receive a completely free 1 year certificate with all the above criteria incorporated. Follow the steps mentioned in https://freesslcert.org/trust-freesslcert-in-browser and you are all set.
Paid Solution for external websites
You can spend some dollars to get a certificate from one of the CA as mentioned here : https://freesslcert.org/get-cert
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 hope this isn't a duplicate.
I'm currently working on client server game based on netty with a client on Android. I'm trying to make a secure login process so I tryed using ssl on top of java socket.
I managed to create a self-signed certificate and to use SSL. The problem is that the example source code i found use à custom TrustManagerFactory which doesn't make any check upon certificate validity. Since I don't wan't to allow Man In The Middle attack i searched for more information on SSL handshake and here is what i understood:
To initiate SSL session, the client send a request to the server.
The server which own the certificate(.jks or .bks) extract public informations into a X509 certificate and send it to the client.
The client check for the validity of the certificate ( In my current solution do nothing)
If check succed retrieve the server's public key from the certificate, generate a random key, encrypt it with the public key and sends it to the server.
The server use his private key to decrypt the randomly generated key.
Both client and server now share the same random key and they start a comunication using this key for symetric encryption ( like AES ).
I don't need to accept certificate from anyone else than my own server so i thought about 2 solution:
Save the X509 on client side and create à custom TrustManager witch only accept this certificate. This solution seems easy to implement but rather hard to maintain since every certificate change on server side would need to update X509 certificate on every client.
Create my own CA certificate sign my ssl certificate with this certificate and manage somehow to tel my client to only trust all certificate signed with my CA.
What i understood about CA authentification is this :
A CA root certificate is a normal certificate that contain a key pair.
signing a certificate with a CA mean adding at the end of the being-signed certificate a hash of the whole certificate encrypted with the CA private key.
this signature is contained in the X509 certificate along with some informations about CA.
To check certificate validity, the client generate certificate hash and compare it to the decrypted hash (using CA public key) contained in the X509 certificate.
So if i'm not mistaking in all of this, if i want to implement my second solution, I need to provide a CA certificate to the client so that he can check certificates. I've seen that it is possible to init à TrustManager with a truststore. I asume it must be a different certificate from the root CA one since the whole security of this depends on my CA private key 's confidentiality. So my questions are :
What should this client truststore contain and how to generate if from my root CA ??
I have red that ssl engine is broken for self signed certificate. So is my second solutions viable on android?
If this can work, how can i invalidate my certificate if i see that someone manage to get my private key somehow? I have red things about crl but i don't know how to generate/use them in my truststore?
thanks in advance.
I can only answer part of your questions:
The truststore should contain your CA, you can generate it with keytool:
http://docs.oracle.com/cd/E19509-01/820-3503/6nf1il6er/index.html
No problem you can implement this in android in the same way than in java using java.security.* and org.apache.http.* classes. One warning, for android versions <=2.3, you could need to implement a workaround as some public CA are missing and it doesn't support miss-ordered certificates chains. I can give you more details if needed.
I don't know
Edit:
A good turorial:
http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html
I've generated a self-signed certificate for my Java app using keytool. However, when I go to the site in a browser it always pops up with a warning - saying this site does not own the certificate - is there a way to self-sign/doctor a certificate so I won't get these warnings in a browser? Both server and browser are located on the same host and I navigate to the site using "http://localhost/". I do not want to add an exception to the browser because I have tests which run on a big build farm so it is excessive to add an exception to all browsers on all build machines.
No, you can't. You might as well ask "How can I make a fake certificate for hsbc.com?"
There are two ways to get a browser to accept a certificate:
Buy a certificate for a domain from a trusted authority (which means proving to that authority that you own that domain) and then use that domain as the name of your test servers
Install your signing certificate into the browsers, so that you effectively become a trusted authority for that browser.
Without touching the browsers, there's no other way to do it - how could there be, if the internet is to remain secure?
You could also setup a self-signed Certificate Authority (CA) using OpenSSL or possibly your Java tool. You can then use that CA to sign a number of server certs.
You are still going to need to manually trust your self-signed CA on all clients that access your test servers, but at least you only have to trust one root CA, rather than a bunch of individual self-signed server certs.
Another option is to check out CAcert.
Is the certificate you created for localhost or for test.textbox.com? If you create a certificate for the FQDN test.textbox.com, that's how you need to be reaching the server to not get those errors, as long as the certificate is properly signed. You can't generate a certificate for the FQDN and then use an IP or an alias (localhost) to access it without being warned that things aren't matching up properly. Or am I misunderstanding your problem?
Make the certificate for "localhost" instead. It needs to match the hostname you have in the URL.
You will still be bothered as the certificate is not trusted, but that is another issue.