This article is about comunicating a jax-ws client with a WCF service using certificates having these conditions:
This is the
<system.serviceModel> part of the web.config file for the WCF service I was trying to comunicate:
... <system.serviceModel> <services> <service name="WSBindingService.Service1" behaviorConfiguration="Service1Behavior" > <endpoint address="" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="WSBindingService.IService1" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <bindings> <wsHttpBinding> <binding name="Binding1" > <security mode="Message"> <message clientCredentialType="None" negotiateServiceCredential="false" /> </security> </binding> </wsHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="Service1Behavior"> <serviceMetadata httpGetEnabled="True"/> <serviceCredentials> <serviceCertificate findValue="put your certificate subject or serial here" storeLocation="LocalMachine" storeName="My" /> <clientCertificate> <authentication certificateValidationMode="PeerTrust" /> </clientCertificate> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
NOTE: In my case I used netbeans as my IDE for the client, but it is not required, if anyone can reproduce these steps in eclipse and have a post about it, I'd like to add a link to that post.
One day your boss tells you "Johny, I need a WCF service and a java client" you creates them and everything goes good until he says, "I need certificates!" I gess this image illustrates the situation:
Once certificates come in play, a myriad of errors pops up in front of you, one of the worst ones is having your client indefinitely trying to talk to the service, no exceptions, zero explosions, nothing that can give you a clue on what is going on.
The first thing is to have your certificates in your project's keystore, there are several ways to do this, that depends on your certificates set. In this case I had a CA signed private certificate (.pfx) from which one can export a public certificate (.cer) the latter is the one we're interested in, to import it one can use this command:
keytool -keystore "path/to/mykeystore.jks" -importcert -alias some_alias -trustcacerts -file "path/to/myCertificate.cer" -keypass yourcertificate_password -storepass mykeystore_password
Once you have your keystore ready, you will need to add a reference to it in your webservice client. Netbeans users may refer to this tutorial.
Configuring my keystore wasn't enough, errors appeared here and there, if my memory doesn't fail, in that moment the client tried to send the messages ignoring any server side security configuration, also, those were the horrible moments of the client trying to talk to the server and sticking forever in it's futile attempt.
After a lot of research (mostly in stackOverflow), a promising solution appeared, the Metro library which is intended to mend faces between Java and .Net, one just need to reference it and it was supposed to do the rest.
Note: Remember to remove any previous reference to jax-ws as that library is included with Metro.
But then, a meaningless
NullPointerException appeared, those were two or three days cursing certificates and viewing this stackOverflow question unanswered. Then I realized that the library version (automatically added by netbeans) was 2.0, updating to the 2.3 version changed the situation, a meaningful exception were thrown and then I could go on, never felt so happy to seeing an exception before!
The exception thrown was:
Exception: "algorithm is not supported for key encryption java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA/ECB/OAEPPadding"
The answer were found here. Apparently, the standard Java installation was missing some encryption algorithms, so it was necessary to install them.
All I had to do was to download this library, add it to the project and add this line of code before calling the service:
Once the encryption algorithm obstacle were passed, the next problem appeared:
Java Security: Illegal key size or default parameters
Man! after a week of problems one feels like Sisyphus!. Fortunately the solution were found by someone else and is here.
Apparently the Java Cryptography Extension (JCE) Jurisdiction Policy Files that comes with the JRE have some kind of limit for something (I don't know what or where and I don't care), it was necessary to replace them with the Unlimited Strength version which can be downloaded here for Java 6 and here for Java 7, make sure to download the correct version for your JRE.
To install them, go to your JRE installation folder and go to the '/lib/security' folder, backup the files inside it and replace them with the ones you just downloaded. Detailed instructions can be found in the README.txt file that comes with the download.
Praise the Lord! Java and .NET finally talked to each other after 8 or 9 days of agony.
In order to comunicate Java and WCF one must:
I hope this article saves some lives, it has a lot of room for improvement, but it may give you clues to point to the right direction, thanks for reading :D