I have developed a webservice in Java. This webservice will be called by other servers, which will have been assigned a certificate from us.
Now I don't know much about SSL, and I have been given a
Root CA
Issuing CA
And I need to check that the certificate provided (when the webservice is called), is "a chain from the root ca". What would be the best way to go about this?
I've read a lot about trustmanagers and keystores, but it's quite confusing and I haven't found anything which is very similar to my question.
I also need to extract a line from the certificate (the 'issued to' field) to use in my application.
Thanks in advance
I have been given a
Root CA
Issuing CA
I need to check that the certificate provided (when the webservice is called), is "a chain from the root ca"
Just put those files, and no others, into your truststore. No code required. See the JSSE Reference Guide.
I also need to extract a line from the certificate (the 'issued to' field) to use in my application
You mean dynamically? when the peer connects? You can get the certificate from the javax.servlet.request.X509Certificate request attribute, and you then just use the certificate API to get the IssuerDN.
Related
SSL certs never ends to dazzle me. I have an web-app and it makes a rest call to another service from a partner to fetch certain data. They use a self sign'ed or an internal CA generated for the Company. The issue is whenever the other end updates there SSL cert, my app fails. This is because the public cert (.cer) that i downloaded from their website and imported in the java trustore of my app doesn't match with their new site. To fix this, i have to re-download their latest public server cert and import again to my java trust store.
Assuming that they use a consistent ROOT CA or an intermediate CA cert to sign their ever changing SSL certs, can i just import the ROOT CA or the INTERMEDIATE CA once and for in my java trust store all to deal with this? So, as long as they don't change the ROOT CA or the INTERMEDIATE CA, my app will be able to make the call.
So their self signed CERT is not built from ROOT CA. Their CERT they generated themselves, so that is why it is considered untrustworthy by default. So every time they generate a new one, this is what happens:
Your app says hello to their server
Their server sends the newly generated CERT which includes information like: Public key, algorithm, cert valid date range, etc.
Your app gets the new CERT and compares it with the old CERT and realizes, oh, these are not the same.
Your app says, well, this is not trustworthy and throws an error.
This is by design because this would be similar to the same result of a man-in-the-middle attack. Your client only trusts certain CAs for that reason. The job of a CA is to certify against certs to see if they are good or bad. If you can add certs on the fly like that without the CA's knowledge, then the CA really has no idea which certs to trust.
So there could be an intermediate Certificate Authority that this company has opened up to you or that they have worked with to provide to you. You would have to ask them to see if they are using some kind of CA at all that you could connect to.
I doubt this the case because you said they are using "self-signed" certs which implies that they are not working with any CA.
I'm having an issue sending our certificate (client) to another server during a web service call.
We're expected to return the certificate with the CN:
b2b-test
however whenever we receive the servers certificate and attempt to send our own, we're getting:
Unable to find valid certificate path to requested target
From my understanding, if I put our certificate b2b-test inside of our keystore jre/lib/security/cacerts, then when receiving the server request, it should send the appropriate certificate.
How does the client know which key from the keystore it should send to the server? Should I be specifying the exact certificate to send during my request, or is it enough for it to be in the keystore?
Currently the server is sending back the certificate
b2b-a
The certificate chain shows:
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=b2b-a, OU=Web Technologies
The URL for the service is:
https://b2b-a/service
If I configure it like one way ssl, and put the servers certificate into our cacerts, then it picks up their cert and fails the handshake (I'm assuming because it's expecting our cert and not theirs back due to it being a two way setup).
I'm a little stumped here. Any clarification on what I've said is greatly appreciated.
The "Unable to find valid certificate path to requested target" error usually occurs when one side passes a certificate for which the other side doesn't trust any of the certs in the chain. You'll generally (always?) see the error message on the side that's receiving the cert (the side that's missing the truststore).
If you're the client and they're the server, one-way SSL would send their cert from them to you and you would validate it (making sure that the hostname matches the content in the cert), but it would not send any cert from you to them nor would they do any validation.
You'll want to make sure you're configuring a truststore that contains either the b2b-a certificate or a certificate that was used to sign it (but that cert doesn't appear to have any root CAs, so you're stuck with directly importing the cert itself). So yes, you want to do what you wrote in your post and put their certificate into your cacerts. And you'll also need to make sure that the b2b-a service trusts the cert you're sending (or a root CA that was used to sign your cert, if any), so you'll need to put your cert into their cacerts as well, or do something equivalent.
Note that putting a cert in cacerts (or in a truststore JKS) DOES NOT send any certs to anyone; any truststore is used only to allow you to validate that you trust the certificate someone else provides you, either because you trust the cert or because you trust a CA cert that was used to sign the cert. No certs are picked out of the cacerts directory to send to another machine.
If you're using a JKS rather than the JRE directory (which is generally a better idea, since you can specify a different set of trusted certs for your process without changing the default set for anyone running a Java project within your JRE), it's possible to use the same JKS as both a keystore and a truststore (you'll just provide the same filename and password for both the keystore and the truststore properties), or you can have two separate files; either approach will work.
From my understanding, if I put our certificate b2b-test inside of our keystore jre/lib/security/cacerts, then when receiving the server request, it should send the appropriate certificate.
Certainly not. That's a truststore. A source of trusted certificates. Don't mess with it. It isn't used for the purpose you require and in any case it is updated every Java dot release, which clobbers your changes.
Your own certificate and private/public key pair should go in a file of your own, a keystore, which is defined to JSSE by the javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword system properties, or by more complex means described in the JSSE Reference Guide.
The keystore is a precious and confidential file containing your private key. Guard and protect it. Private key leakage would compromise your security and identity.
I got list of URLs, and I want to validate their Extended Validation (EV) attribute using JAVA
I can make request and get their certificate, but I am not sure how to validate “Extended Validation” for a given site.
Is there any special value in certificate? Or any attribute?
Extended validation is mostly useful from a user-interface perspective. It's not so useful if your client doesn't have anything in its user interface to display the certificate. These verifications are not integrated by default in the JSSE, possibly because there is little demand for it (lack of Java browsers). (By the way, you should verify the certificate you get upon connection, not check with a first connection and connect with another, just in case).
The specifications are defined by the CA/browser forum.
The OID values and root CA certificate fingerprints are hard-coded into browsers (see security/certverifier/ExtendedValidation.cpp in Firefox, used to be in in security/manager/ssl/src/nsIdentityChecking.cpp). There is also a list on Wikipedia for reference, although in principle you should check the policy OIDs with each CA.
To analyse the extensions, it might be useful to use BouncyCastle if X509Certificate.getExtensionValue() isn't enough.
One problem you will have to watch out for is that the hard-coded SHA-1 fingerprints of the root CA certificates need to match exactly those certificates in the trust store. Some CAs renew their CA certificates once in a while in the bundles that are shipped with most browsers/OS/JREs: make sure you're using the same.
I am implementing a VB.NET desktop application which consumes a web service.
The web service implemented in Java and I currently using Tomcat on my localhost to host the web service.
The web service requires secure communication with the client and so I have followed instructions that outlined how to use Java's keytool.exe to create two .jks keystores (one for the client and one for the server) and then create two .cer certificates (one for the client and one for the server)
I have placed the keystores and certificates generate into the directory where the web service is expecting them (according to the instructions)
I have installed the certificates into TrustedPeople and have attempted to use the certificate by setting the ClientCredentials.ClientCertificates property like this:
myServiceProxy.ClientCredentials.ClientCertificate.SetCertificate(storeLocation.CurrentUser, StoreName.TrustedPeople, X509FindType.FindByIssuerName, "name")
I keep getting the following error message when I try to call any method:
An error was discovered processing the <wsse:Security> header
My problem is that I don't know how to use this in the VB.NET client application that is consuming the web service. I could be doing this completely wrong. Any guidance on this topic would be greatly appreciated.
Thank you,
-Frinny
While I haven't coded VB for 10 years, this should get you started: http://www.example-code.com/vbdotnet/ssl_client_certificate.asp
especially this looks like it is loading the file containing the certificate:
certStore.LoadPfxFile("chilkat_secret.pfx","secret")
and this extracts the certificate and uses it for the connection:
Dim cert As Chilkat.Cert
cert = certStore.FindCertBySubjectCN("Chilkat Software, Inc.")
If (cert Is Nothing ) Then
MsgBox(certStore.LastErrorText)
Exit Sub
End If
socket.SetSslClientCert(cert)
When I had to work with certificates and WS, I had lots of issues with the them too. Use the certificates MMC and verify:
That you placed the certificate in the correct place. Note that there is a CurrentUser store, Machine Store etc. Make sure you put the certificate in the correct one according to your code.
Which user is running your application? Is the certificate located in it's store? The certificate must be visible to the user.
Open the certificate and make sure it is trusted (you will see a warning if not). You may need to put your CA's certificate in Trusted Certification Authorities store.
Make sure that the algorithms you use on each side are supported by the other side.
Note that you are looking for the certificate by issuer name X509FindType.FindByIssuerName, "name" open the certificate, make sure the issuer name matches (I guess not since it seems like copy&paste from example).
If all of this fails, try to experiment with the certificate location (I vaguely remember some issue with being able to use certificates from one location and not the other), and with the property you use to search for the certificates.
Plus, since you asked about certificates I answered about certificates. It's a good idea to check if there's an inner exception and see - it may be another problem.
I use SSL to communicate between two components written in Java. I can't use a CA, so I have to self-sign everything. Unfortunately, this means that when I try to handshake, I get a SunCertPathBuilderException. I can create my own X509TrustManager that just trusts everything, but that sort of defeats the purpose of having a signed cert.
I would like, when first making the connection, to prompt the user with "SSL handshake with invalid cert. Add cert to store?" or something so they could have it added for them to their certificate store, like web browsers do at sites with invalid certs. I can find plenty of examples online of adding a cert to the store through the commandline, but I can't figure out how to do it programmatically. Is there a way to do this?
Yes it is possible.
There is some code here that I've used before. I had to modify it to do what I wanted and I suspect that you will too but this should get you close - you aren't trying to import a key so theoretically you should be able to simplify things. In any case you can get an idea of what you'll need.
The JDK JavaDoc for java.security.KeyStore is pretty useful too.
Why don't you create your own CA and sign your certificates with that? Then all you would need to do is install the CA own certificate on the machines and every certificate signed by that CA would validate.
Why would you need to do this, you are not validating that the client is who they say they are you are only using the certs to encrypt the comms, so a custom trust manager that allows all certs is all you need.
What you are asking is possible and from memory also involves a custom trust manager to validate the certificates and store them in the keystore. I can't remember the details, but at least you know it is possible to do it.