WCF Using X509 Private key for outgoing messages - c#

So, here is my million dollar question. I want to consume a service hosted by a third party, and therefore for the set up we exchanged X509 certificates. I sent them ours and we got theirs. I added their self signed certificate in the certificate store. Now, I have tried to connect to the services with soapUI, where i need to create a JKS file with my private key to connect, and use the WSSE headers for username, password, nonce and TTL and it works just fine.
But, I want to write a WCF c# client to communicate with the service, and adding my certificate to the client credentials in the config or through code does not work. Can someone please let me know how to use the private key for out going messages using WCF?
I have tried both these things, but not sure where am i going wrong...
proxy.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(#"C:\soapUI\soapUI\Agency1\certificates\myprivatekey.pfx", "Pwd");
proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(#"C:\soapUI\soapUI\Agency1\certificates\myprivatekey.pfx", "Pwd");
i have also added the correct wsu and wsse headers to the soap envelope. When i take the soap envelope from the WCF client to SOAPUI, it works, but not from WCF itself. So i am pretty sure its the difference in how the private keys are being used. So any line of thought will be helpful.

In this article, we will start with transport and message security understanding. We will then see simple code samples of how to implement transport and message security using WsHTTP bindings. We will also see the differences between ‘BasicHttpBinding’ and ‘WsHttpBinding’ with the help of a simple code. WCF security is a huge topic by itself, but I am sure with this article you will get a quick start of how to go about WCF security.
http://www.codeproject.com/Articles/36732/WCF-FAQ-Part-3-10-security-related-FAQ

Related

WCF Client to WSE 3.0 service Exception: CWWSS7310E: XML encryption information[.....]

I have never worked with soap services before, so I might have done something wrong. I have generated a service client reference for the service through it's wsdl with "Svcutil".
I have followed this guide https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-wcf-client-to-interoperate-with-wse3-0-services and set up the custom binding.
After that I a client from the reference and supply a new binding that is using WseSecurityAssertion.MutualCertificate10 and the service endpoint address.
I then add a certificate and add theese credentails to the service client:
clientProxy.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(string.Concat(xxx, yyy), GetCertificatePassword(xxx), PersistKeySet);
clientProxy.ClientCredentials.ServiceCertificate.DefaultCertificate = new X509Certificate2(xxx, "", PersistKeySet);
clientProxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = ChainTrust;
clientProxy.ClientCredentials.ServiceCertificate.Authentication.RevocationMode = NoCheck;
This is code that have worked before (but before using wcf and "Svcutil") and I have mostly copied it, but refactored it a bit.
When I call the Web Service I get this error:
System.ServiceModel.FaultException: 'CWWSS5511E: An exception occurred during the decryption of a message. The exception is CWWSS7310E: XML encryption information exists in the security header, however an inbound XML encryption configuration is not present.'
I understand that I encrypt something that I shouldn't and when I compare the request I sent with the old code to the request I send now I can see that this is added in the securityheader:
<e:EncryptedKey Id="_0" xmlns:e="http://www.w3.org/2001/04/xmlenc#"><e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns="http://www.w3.org/2000/09/xmldsig#"/></e:EncryptionMethod><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
And some info about the key.
I'm wondering what it is I do wrong that the code didn't do before. I can't find any config files so I don't think it's some configuration I have missed. Where might this encryption be set? Is it inside the binding or is it where I set clientCredentials?
So after alot of reading and comparing I finaly figured out that I did not set
ProtectionLevel to System.Net.Security.ProtectionLevel.Sign in the new generation of the service reference file. this was probably hardcoded there in the old ones instead of using a config file to set the ProtectionLevel.
This is what caused the service on the service side to not understand how to decrypt it correctly.

.NET SOAP communication with separate certificates for signing and encryption

I try to configure client communicating with SOAP service written in Java, yet I failed so far. While it's pretty easy to connect with that service using SoapUI (I just need to put these two certificates in adequate places and it just works) it's pretty far from being easy (and intuitive) in C#.
Service uses two different certificates - one for signing message (binary token) and one for TLS encryption. I implemented my own classes for that thing using this tutorial:
https://learn.microsoft.com/pl-pl/dotnet/framework/wcf/extending/how-to-use-separate-x-509-certificates-for-signing-and-encryption
Thanks to that I'm able to connect and send request, but that's not the end of the problems. Next error was "The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected."
According to my research I should just erase whole Security header and configure my client to allow unsecured response. Therefore I should implement my own MessageEncoder what I actually did using this:
https://learn.microsoft.com/pl-pl/dotnet/framework/wcf/samples/custom-message-encoder-custom-text-encoder
I only added one extra function that should erase security header, just like #nuronce did in this thread:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/16de05ed-3776-40e5-b576-139603e4b374/the-incoming-message-was-signed-with-a-token-which-was-different-from-what-used-to-encrypt-the-body?forum=wcf
But that's still not the end of the problems... Right now it says: "The message version of the outgoing message (Soap11 (http://schemas.xmlsoap.org/soap/envelope/) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)) does not match that of the encoder (Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)). Make sure the binding is configured with the same version as the message."
That's weird because in every place with MessageVersion property in my custom encoder classes it's set to MessageVersion.Soap11 as default value that should not be modified, because I don't change anything in my CustomTextMessageEncodingBindingSection.
For every solution WCF gives me another problem and I'm losing my patience for that, because these solutions are not so easy to find and adjust to my needs. I'm also pretty sure that even if I go through my current problem - I will find another one, maybe harder or even impossible to resolve.
Are there other .NET libraries that will allow me to use two different certificates by default and save my code from growing, hard to understand convolutions? And if there is none, how can I deal with WCF?

WCF Protectionlevel, why is there no 'encryptOnly'?

I'm attempting to make a client that uses WCF to communicate with a SOAP endpoint made in Java. The service requires me to send my PKCS10 request inside a encrypted SOAP request, using a X509 certificate that I have received from the service using another function, but I can't figure out how to configure WCF properly to allow me to only encrypt but not sign, seeing as I have yet to receive my final certificate from the service.
I've tried to set the X509 certificate I've received from the server as both DefaultCertificate for the service and the ClientCertificate, but no matter what kind of options I set for the binding and endpoint, I always end up with the error "The private key is not present in the X.509 certificate" and that's because (I assume) there are only the following ProtectionLevels in WCF:
None
Sign
EncryptAndSign
I understand the error here because obviously I haven't received the service's private key and setting the service's certificate as the ClientCertificate I would expect this error, but is it me who has misunderstood something here?
Shouldn't it be possible for me to just encrypt the SOAP envelope using the service's public key that I've already received, without having to sign it as well with my own private key (which I haven't actually received yet)?

Incorrect Key for decrypting web service response

I am working on a WCF client to consume a third party web service over which I have no control. It works with a custom binding and WS Security. No app.config, all through code. I can successfully send requests and receive responses. However, it seems .Net cannot decrypt the service responses, so I have to do it manually. I have implemented a custom encoder and overriden the ReadMessage method. I have access to the raw SOAP response. I have seen code in MSDN as well as a blog where they explain how to decrypt the response. I read the oasis specifications for the response xml schema. The response contains a reference to the x509 certificate that has the private key necessary to decrypt the session key, so then the body can be decrypted. According to the documentation of the service I am trying to consume, and pretty much everywhere I've read, I should use the private key of the certificate I used to sign my request, but I get an Exception saying the key is incorrect. I then tried every possible certificate with a private key in all my certificate stores to see if one of them would successfully decrypt the message but all of them failed. If I understand it right, this means the service expects me to decrypt the message with a private key I don't have. I'm rather new to WCF and web services themselves, so I might be missing something.
Do you know what could be happening? Or maybe I am understanding something wrong. Any help will be greatly appreciated.
Thanks

Invoking Java web service from C# client using JKS and/or PFX certificates

I basically need to secure my requests towards this service.
I've been provided a JAR test client and two files, trust.jks and Client.pfx, but I have no clue how to use them: I understand X509Certificate2 class is involved in some way.
The command line to execute the test client is the following:
java -Djavax.net.ssl.trustStore=trust.jks -Djavax.net.ssl.trustStorePassword=******** -Djavax.net.ssl.trustStoreType=JKS -Djavax.net.ssl.keyStore=Client.pfx -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStorePassword=******** -jar TestClient.jar https://myServiceurl
It works, so I can both see the service, and the service itself should be properly configured.
My C# client (it's targeting .NET 2.0) uses a normal Web Reference to perform requests:
wsReferenceClient service = new wsReferenceClient();
//certificate code here ?
//maybe service.ClientCertificates.Add(<X509Certificate2 object built somehow>); ?
service.MyRequest(myParameters);
Server settings should be setup properly.
I fumbled around with the X509Certificate2 methods but I can't come out with something that makes sense, so the answer to the 'what have you tried?' question at the moment is 'I don't really know what to try in the first place'.
Any help would be really appreciated.
Turns out I don't need to do anything with the JKS file.
wsReferenceClient service = new wsReferenceClient();
X509Certificate2 cert = new X509Certificate2();
cert.Import("Client.pfx", "<the password>", DefaultKeySet);
service.ClientCertificates.Add(cert);
service.MyRequest(myParameters);
This allows my HTTPS requests to go through successfully.

Categories