So this may be a stupid question but I have been scouring the internet all day trying to figure out how to get a trusted SSL certificate into my java server.
Details:
I created a java server that creates an SSLServerSocket accepts connections. I used keytool to create a keystore called domain.key as well as a certificate request (csr). I then contacted a certificate authority (starfield) and gave them my csr, they did their thing and returned to me the certificates (crt). I have 3 of them. one is called domain.com.crt, one is called sf_bundle.crt, and one is called sf_intermediate.crt
After much searching I found that I need to import the certificates into a keystore and that the keystore can be the same one that has my public/private keys or it can be in a seperate file. I chose to put it into a seperate file called domain.trust.
I then modified my server to import the trust store as well as the keystore using:
System.setProperty("javax.net.ssl.keyStore", "domain.key");
System.setProperty("javax.net.ssl.trustStore", "domain.trust");
along the corresponding lines for the keystore password and the truststore password.
The problem is that when i try and connect using any client it always says that the certificate is sell signed.
I have been using http://certlogik.com/ssl-checker/ to test it.
I obviously have missed a step but I cant find out where.
Any help would be greatly appreciated
The problem is that when i try and connect using any client it always
says that the certificate is sell signed.
This indicates that the root CA certificate is being send to the client.
You don't mention how you created this separate keystore you use.
You should be doing something like the following:
keystore.setKeyEntry("alias", privateKey, password, chain);
And chain would have:
chain[0] --> Your server's certificate
chain[1] --> The signer's certificate
....
chain[N] --> Signer up to the root
You first need to understand what happens during an SSL Handshake. Maybe then you can narrow down the problem. You can refer to various docs on internet., http://www.pierobon.org/ssl/ch/detail.htm
Your running server must have either have the CA StarField installed in it. Or it should have a trust relationship with the CA StarField.
You rclient certificate must be CSR signed by CA StarField, which I guess you have already done.
Now when you present your certificate to the Server, it checks with the CA's it has.
So, if the Sever has the CA StarField and your certificate is signed by StarField then there is no way you would get the Self Signed error.
You get that only when your certificate is not signed by the CA. Just open your certificate and check it's Issuer details to confirm.
Firstly, you seem to be confused about the difference between keystore and truststore. This answer may be of interest.
Essentially, unless you want to use client-certificate authentication, you have no need to change the trust store, from a server point of view.
After much searching I found that I need to import the certificates
into a keystore and that the keystore can be the same one that has my
public/private keys or it can be in a seperate file.
To be able to use the certificate you got from the CSR you initially had, you MUST import that certificate back in the keystore with which you generated the CSR, and you MUST import it, along with the whole certificate chain, into the correct alias, where the private key is stored.
This is essentially the same problem as the one in this question, but from the server side here.
Find the alias name that has your private key using keytool -list -keystore store.jks:
Your keystore contains 1 entry
myalias, Feb 15, 2012, PrivateKeyEntry,
Certificate fingerprint (MD5): xxxxxxxx
The prepare a bundle with your certificate and the chain of CA certificates in the right order (your own certificate first, and then each issuer one by one):
-----BEGIN CERTIFICATE-----
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa
....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV
....
-----END CERTIFICATE-----
(You can verify the content of each certificate using openssl x509 -text -noout and pasting each ---BEGIN/END--- block, including delimiters into its standard input.)
Then, import that file in a single step:
keytool -importcert -keystore store.jks -alias myalias -file bundle.pem
Related
Can someone please help me with the following, I googled before hand but did not find a blog outlining what I wanted to do, thanks in advance.
I have and internal test PKI (based on AD CS). I have imported the Root CA certificate and the Issuing CA Certificate (minus their private keys) into the CACerts java key store (keying the GUI tool "KeyStore Explorer 5.5.1"
I have a leaf (end-entity certificate) 'outside of the Java keystore' as I want to simulate a situation where the client would obtain (be given) the leaf certificate via a WEB browser (for example when opening a TLS connection to a WEB server).
The leaf certificate is stored in a .pem flat file on the same computer where it was create (using Windows default method so private key for the cert is in the Windows keyStore). The computer also contains the Java KeyStore CACerts (where I imported the CA certs as above) and the Java JDK (so Keytool.exe for example)
So what I need to do (ideally using Keytool or a pre-made script suitable for Windows) is point to the leaf .pem certificate and say go check the certificate chain of this leaf certificate but using the CA certs held in CACerts keystore
Can someone kindly tell me how to do this as the only examples I have seen this far are about checking the chain for certs already in the CACerts keystore. Whereas I want to check the chain of a .pem flat file against the CA certs held in the CACerts java keystore
UPDATE: After I have found a solution, I edited the question to be more clear for future reference.
I've got a corporate (ie not well known) CA certificate from a company which provides us a web services to be called from Java. I added this CA certificate to default cacerts trust store (keytool -import -file cert.cer -alias myca -keystore jre/lib/security/cacerts), but connection to the service still fails with the dreaded "PKIX path building failed" message. I have checked that issuer field of the end server certificate is the same as in the CA certificate and also validity dates is ok.
I don't know how to explain this. I can think of the following reasons but I don't know which one is true:
I have noticed that when I add also the end server certificate to trust store, the connection is OK. Maybe cacerts by design don't work as I expect (ie all the certificates signed by an authority added there are considered valid), but instead I have to add all the end server certificates to a trust store including CA certificate of their issuer.
I have to add CA certificate in some other way - by different command, to different file etc.
Maybe the CA certificate is not correct and keytool refuses to consider it a certificate authority.
Maybe PKIX path building fails for other reason.
How can I debug this problem more to find an answer?
Details:
The end server certificate is wildcard certificate
There is no intermediate certificate, just root and the end certificate
I was facing the same problem with "PKIX path building failed" with Let's Encrypt signed certificates at a time Java didn't incorporate the Let's encrypt CA certificate in its default trust store.
My story is written in detail here: http://blog.novoj.net/2016/02/29/how-to-make-apache-httpclient-trust-lets-encrypt-certificate-authority/
At the end I was able to make Java trust "the end of the chain" server certificate by creating internal trust store embedded in my application that contains only root CA certificate (and the backup one).
I much more prefer creating internal application truststore than importing certificate in main Java trust store for two reasons:
you don't need another extra step in install procedure for initializing the global trust store
you limit "the trust" to you application and don't affect another applications running on the same JVM (or better you can even limit the trust to the certain instances of client objects in your application if required)
Maybe I had a different scenario than you're facing, so downvote me if I didn't get the point.
The trust store needs to contain the root certificate (the CA's cert).
I'm not sure if that's what you mean by "the last one I'm the chain", but the CA certificate should be the last one in the certificate chain presented by the server.
If your certificate is signed by a well-known CA, then the CA cert should be in the trust store, and if the server's certificate chain is set up properly, everything should just work.
If yours is a self-signed certificate, then the root certificate will not be in the trust store, and you will have to add it.
Thanks to #pedrofb comment I found out that the reason PKIX path fails is simply that the CA certificate I got is not the CA that signed the end certificate. What made it so complicated is the monstrous incompetence of company that gave me the CA certificate which obviously has two CAs with almost the same description (cn, o, st, c) which differs only in SN and which both issued the same wildcard certificate. Only after I became super paranoid and compared the SNs, I understood the problem.
I have a certificate for a Glassfish server within a Java keystore. It has a 4part certificate chain, which I can see with the list command. Now one of the intermediate CA certificates has been revoked and I have to change the chain of my certificate, because it is now untrusted.
In the Windows IIS I have added the new intermediate certificate to the certificate store and all was fine. For the Java keystore I have no idea how I could do that? Should I export the certificate incl. the chain as PEM and replace the text parts for the intermediate CA? The CA says, I don't have to use a new certificate, it is only necessary to correct the chain, so it makes no sense to generate a new certificate request.
Any ideas?
Is it possible to regenerate a private key in a .JKS keystore using keytool or equivalent?
I've been supplied with a certificate and a JKS keystore, but on importing the cert it looks like the private key that was used to generate the CSR has been deleted.
I can see how to create a new keystore with a new private key, but this won't then match the CSR or certificate.
No, that's the whole point of asymmetric cryptography: making it impossible to produce the private key when knowing only the public key (which is contained in the CSR and in the certificate).
If you could re-generate the private key only from the CSR or the certificate, anyone could impersonate the entity to which the certificate has been issued.
If you've lost your private key, you'll simply have to create a new key-pair, submit a new CSR and get a new certificate. Some CAs allow this sort of re-keying for free as part of their contract within the duration of the initial certificate.
EDIT: Just to clarify what a CSR is.
To apply for an X.509 certificate, you must:
Generate a public/private key pair. By nature, the public key can be publicly distributed, because it's not sufficient to obtain the private key (at least not in a reasonable time).
Submit that public key with your identity information to the Certification Authority. This can be done using:
A Certificate Signing Request (CSR, PKCS#10), which contains your public key and the data you would like to be in the certificate (e.g. the Subject DN you want). Although very similar to the data in a certificate, this data should mainly be used by the CA for identifying the request itself, since CAs doing their job properly should check what they put in the certificate, not just turn the CSR into a certificate blindly. The CSR itself is signed using the private key matching the public key in the certificate. It's effectively very similar to a self-signed X.509 certificate (without Issuer information and validity dates), but isn't one.
SPKAC or CRMF for in-browser certificate applications.
The CA then takes this CSR (or equivalent) and makes the necessary verification outside this process to vet the pieces of information it wants to embed in your certificate, and issues your certificate (by signing it with its own private key). It's effectively vouching for the binding between your public key (extracted from the CSR) and the information it embeds in the certificate (e.g. your name and/or the domain name for which this cert is). It sends you back this certificate.
You then have to use this certificate in conjunction with the private key matching its public key. Some tools do this using separate files, it's also possible to import the cert back against the private key entry in a keystore.
Having the CSR or the cert without the private key is of no use. You can quite easily create a new CSR again, but you'll also need to create a new key pair. The most important part of the CSR is the public key, and to have the matching private key. You can discard the CSR otherwise.
Is it possible to regenerate a private key in a .JKS keystore using keytool or equivalent?
Yes, but regenerate the private key and CSR. The CSR is submitted to the CA where you are provided a new public key.
You can reimport to the keystore anytime using the following command:
keytool.exe" -import -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -file .\certificate.cer
Make sure you also import the certificate to both paths for the newer JDK releases:
C:\Program Files\Java\jdk1.6.0_31
The newer releases also deploy a separate JRE:
C:\Program Files\Java\jre6
Failure to do so may result in the following exceptions in log:
Caused by: 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
To regenerate your private key and CSR, you can use the following command:
$ openssl req -new -newkey rsa:2048 -nodes -keyout private.key -out signing request.csr -config openssl.conf
I had the same trouble (my private key was accidentally deleted from keystore) and there was just one way to recover it: replacing the keystore file (*.jks) with a backup. So I recommend to always make backup with all files related to SSL, and if you delete anything by mistake on keystore just replace the file with an older one.
Is it possible to use a server certificate to sign a java web start app? What I want to know is if will it work. I have a trusted certificate for my server, and I would like to reuse the same certificate to sign an app.
Right now, I have this warning:
This jar contains entries whose signer certificate's ExtendedKeyUsage
extension doesn't allow code signing. This jar contains entries whose
signer certificate's NetscapeCertType extension doesn't allow code
signing.
Will I be able to launch my app without the warning that the certificate is not trusted?
You will get warning if you don't use a code signing certificate. For most CA, code signing cert costs more than the server cert. In my opinion, this is just a marketing scheme to make you to pay for another cert. There is no technical difference between two certs. Some CA may provide combo deals with usage for both.
I assume you have created the JKS file using the KEY and CRT of your SSL and hence you get the error..
I have a simple solution here:
As you know you can create a JKS using the following command
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
and when you use this JKS you get self signed certification message which is absolutely fine to make the app live at Google play store.. But buying code signing certificate is good if you can afford it ..