Wednesday, September 29, 2010

WCF: Server signs response with a different certificate than client uses for encryption

@YaronNaveh

A lot of Wcf users encounter the below error when consuming a secured non-Wcf web services:

The incoming message was signed with a token which was different from what used to encrypt the body.  This was not expected.

Understanding the problem

When we configure the service x.509 certificate in the client the latter sees this certificate as the service identity. So whenever we interact with this service the client verifies that this certificate is still the service identity, and if not it assumes some sort of phishing occur and drops the connection.

example

This is our client config:

<behavior name="NewBehavior0"> 
 
<clientCredentials> 
   
<serviceCertificate> 
     
<defaultCertificate findValue="CN=WSE2QuickStartServer" /> 
    </
serviceCertificate> 
 
</clientCredentials> 
</behavior> 

We have declared the above certificate here since we want Wcf to use it for encryption and to verify signature. Wcf does all this and also something else: it assumes this is the service “identity”. We’ll see how this afefcts us later.

This is our client request:

<Envelope> 
… 
 
<EncryptedKey> 
   … 
   
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"> 
     
<wsse:SecurityTokenReference> 
       
<wsse:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">asPwlS8jh3W+klJJov4=</wsse:KeyIdentifier>  
     
</wsse:SecurityTokenReference> 
   
</KeyInfo> 
   …  
 
</EncryptedKey> 
… 
</Envelope> 

The client uses the service public key to create a session key which is used to encrypt the request body. Only the owner of the matching private key knows how to decrypt this and since this owner is the server the client gets the authentication it wants.

This is the service response:

<o:BinarySecurityToken wsu:Id=”uuid-a687c39f-f848-481b-8552-35de5b5a4d51-2”> 
MQ+PASL89QWEQW2367ASDDASjn7812ASDDAS781mFSDJK78…
</o:BinarySecurityToken> 
 
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> 
   
<SignedInfo> 
     
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod> 
     
<SignatureMethod Algorithm="...rsa-sha1"></SignatureMethod> 
       … 
   
</SignedInfo> 
   
<SignatureValue>tWTQzQhKg3zJb75P4sUfMPa3...</SignatureValue> 
   
<KeyInfo> 
     
<o:SecurityTokenReference> 
       
<o:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-a687c39f-f848-481b-8552-35de5b5a4d51-2"></o:Reference> 
     
</o:SecurityTokenReference> 
   
</KeyInfo> 
</Signature> 

The service signs the response message. Anyone who has the service public key can now verify that the service is the one who sent this response and not some MITM. And since our client has the server public key (it’s the one we configured in the config, which is the same one the client used for encryption) the client can now validate the signature source.

So when do we get this “signed with a different token” error?

We can see in the service response a “binarySecurityToken” element. The service uses it to notify the client which certificate it used for signature. The content of this element is just a base-64 encoded certificate, so the client can easily extract it and compare to the certificate it has configured for the service. If they are not the same we get this exception.

Why must they be the same?

Remember that when we configure the service certificate on the client, Wcf treats it as the service identity. When a response comes back the client expects the service to prove its identity by signing the response with its key. If the response is signed – but using a different key – Wcf throws this authentication error since service identity has not been proved.

I am not using any encryption. Why do I get this error?

Even if you use ProtectionLevel.Sign, Wcf still requires you configure a service certificate. Since the service signs the response Wcf will compare the signing token to the certificate you configured.

Solution

If there is indeed a requirement for the service to use a different signing and encryption certificates, what we would like to do is to configure both of them on the client, so Wcf would know that both of them can authenticate the service. Unfortunately Wcf only allows us one slot of service certificate per configuration. So we need to look in other places.

Option 1

If the scenario is Wcf-2-Wcf, and we are ready to use the proprietary duplex communication, then there is a way to use separate X.509 certificates for signing and encryption.

Option 2

If we use ProtectionLevel.Sign, meaning we only sign messages but do not encrypt them, then the service certificate which we configure on the client is only used for the purpose of validating the response signature. So we are free to change it to be the actual signing certificate. In some cases we may not know what this certificate is. Apart from asking the service author to provide it we can examine the response (as above) and extract the certificate from the binary security token (which may not always exist though).

Option 3

This is a workaround that reduces the security level of the communication. Use it only if you have other means to verify the service apart form the signature or if you are willing to have reduced security.

Step 1: Implement a custom message encoder which removes from the response the Envelope/Header/Security element all together.

Step 2: Configre EnableUnsecuredResponse to true:

<customBinding>
 
<binding>
   
<security enableUnsecuredResponse="true" />
  </
binding>
<customBinding>

This is a Wcf 4.0 new feature but it is also available in a patch to Wcf 3.5 SP1. Strive to use 4.0 if you can since some users have problems with the patch.

This solution requires to use a custom binding. If you need help converting your wsHttpbinding to a custom one use the binding converter.

The implication of this workaround is that your client will not verify the service identity at all – this is usually not desired from security perspective.

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!

31 comments:

Anonymous said...

Thanks Yaron!
Excellent Tutorial.

In this scenario (WCF (client) - AXIS2 (server), WSSecurity MutualCertificate, Sign Only), the server certificate must be installed on the client in order to verify the server response?

I'm getting:
"The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected"

I cannot trust in Root Authority in order not to need to install the server certificate?

Really thanks

Yaron Naveh (MVP) said...

Annonymous

the error is not related to the service installation. It is because you encrypt the message with one certificate ("server certificate") but the server response uses a different certificate. Wcf does not expect this.

Anonymous said...

Thanks Yaron,

Yes, that's right.
(My scenario is sign only, not encrypt).

I'm signing the SOAP message with my private key (WCF is doing this..).

I'm getting the server response signed with server private key.

WCF needs the client to "trust" the public certificate of the server in order to verify the server response, right?

What I did was to extract the BinarySecurityToken of the server response, converted it to X509Certificate and installed on the client PC.

Now it's working, no WCF error message.
Is this procedure ok?

Despite having resolved the WCF issue, it seems that the server service (IBM DataPower WSSecurity) has some issue with that.

Yaron Naveh (MVP) said...

if it is working then it is ok, though I don't see how what you did should solve the error you got above, it was not a matter of trust.

Jagadeesh said...

Dear Yaron,

I am programatically setting the certificates(client & service), ofcourse using the same certificate for both as shown below:

//Client Certificate
X509Certificate2 x509Cert = new X509Certificate2(CertficatePath, CertPassword);
_proxy.ClientCredentials.ClientCertificate.Certificate = x509Cert;

//Service Certificate
X509Certificate2 x509Cert1 = new X509Certificate2(CertficatePath, CertPassword);
_proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = x509Cert1;
_proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

Also I am using ProtectionLevel.Sign attribute.

As you suggested, I have tried setting Enable unsecured response as shown below:

asymmetricSecurityBinding.EnableUnsecuredResponse = true;

But, still I am receiving the mentioned error (i.e.) "The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected."

Is my case different from the one you described. Please Help me.

Thanks in advance.

Kind Regards,
Jagadeesh

Yaron Naveh (MVP) said...

@Jagadeesh - I know you solved it, so great work

Santiago Moreira said...

Hi. I am having the same problem. I use protectionLeve.sign.

I do not understand your "Option 2".

Can you explain me a little more?
Here I leave some code...

proxy.ChannelFactory.Credentials.ClientCertificate.Certificate = cert
proxy.ChannelFactory.Credentials.ServiceCertificate.DefaultCertificate = cert


proxy.ClientCredentials.ClientCertificate.Certificate = cert
proxy.ClientCredentials.ServiceCertificate.DefaultCertificate = cert




























Yaron Naveh (MVP) said...

Hi Santiago

Please send me in mail the request and response you have.

raki said...

Hi yaron,
I keep getting the same error.
This is how i am Using it
EndpointAddress add = new EndpointAddress(new Uri("https://misapi.ercot.com/2007-08/Nodal/eEDS/EWS/?wsdl"), id);
CustomBinding cbinding = new CustomBinding();
var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10); sec.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
sec.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
sec.EnableUnsecuredResponse = true;
//sec.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
sec.IncludeTimestamp = false;
sec.AllowSerializedSigningTokenOnReply = true;



ChannelFactory factory = new ChannelFactory(cbinding, add);

factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "API WSDL SQ3");

factory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "API WSDL SQ3");

Operations client = factory.CreateChannel();


I have ProtectionLevel = System.Net.Security.ProtectionLevel.Sign. I don't Knwo what to do or how to solve this Issue.

raki said...

EndpointIdentity id = EndpointIdentity.CreateDnsIdentity("API WSDL SQ3");
EndpointAddress add = new EndpointAddress(new Uri("https://misapi.ercot.com/2007-08/Nodal/eEDS/EWS/?wsdl"), id);
CustomBinding cbinding = new CustomBinding();
var sec = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10); sec.EndpointSupportingTokenParameters.Signed.Add(new X509SecurityTokenParameters());
sec.MessageSecurityVersion = MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
sec.EnableUnsecuredResponse = true;
sec.MessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
sec.IncludeTimestamp = false;
sec.AllowSerializedSigningTokenOnReply = true;

cbinding.Elements.Add(sec);

var tme = new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8);
cbinding.Elements.Add(tme);
HttpsTransportBindingElement http = new HttpsTransportBindingElement();
http.MaxBufferSize = 999999999;
http.MaxReceivedMessageSize = 999999999;
http.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
http.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
http.ProxyAddress = null;
http.UseDefaultWebProxy = true;


cbinding.Elements.Add(http);

ChannelFactory factory = new ChannelFactory(cbinding, add);

factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "API WSDL SQ3");

factory.Credentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "API WSDL SQ3");

Operations client = factory.CreateChannel();

MarketTransactionsRequest mr = new MarketTransactionsRequest(reqmsg);

MarketTransactionsResponse mrr = new MarketTransactionsResponse(resmsg);

mrr = client.MarketInfo(mr);

Yaron Naveh (MVP) said...

raki - make sure the ServerCertificate is configured to be the public certificate that corresponds the private one the server uses

Desi English Jetlag said...

HI Yaron,


I have been going through your various posts for my project, it has been very helpful till now.
But I am stuck in situation , so I thought I will bug you.

My request is being processed by Java Webservice (blackbox) but my client is not able to process the response.

I am getting following error, that I am not able to solve.

"The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected."

I have through your article :http://webservices20.blogspot.in/2010/09/wcf-server-signs-response-with.html.

Option 1 ,Option 3 of the article I cannot use them.

I tried option 2 , but gives me following error :


The identity check failed for the outgoing message. The expected identity is 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint)' for the '[https: service link]' target endpoint.


If I change certificate in [endpoint/identity/certificate] or [serviceCertificate/defaultCertificate] , then I get above error.

It will be great help , you show some direction .........



In my project we consume a Java webservice , by C# client (4.0).

I need to sign the message by x509 certificate (no Encryption).
(As per your article, I am using ProtectionLevel = System.Net.Security.ProtectionLevel.Sign )


As per your article following my binding :













Till now I been able to navigate through various issues with help of various posts but I have hit a dead end.


Regards
Tushar

Desi English Jetlag said...

HI Yaron,


I have been going through your various posts for my project, it has been very helpful till now.
But I am stuck in situation , so I thought I will bug you.

My request is being processed by Java Webservice (blackbox) but my client is not able to process the response.

I am getting following error, that I am not able to solve.

"The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected."

I have through your article :http://webservices20.blogspot.in/2010/09/wcf-server-signs-response-with.html.

Option 1 ,Option 3 of the article I cannot use them.

I tried option 2 , but gives me following error :


The identity check failed for the outgoing message. The expected identity is 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint)' for the '[https: service link]' target endpoint.


If I change certificate in [endpoint/identity/certificate] or [serviceCertificate/defaultCertificate] , then I get above error.

It will be great help , you show some direction .........



In my project we consume a Java webservice , by C# client (4.0).

I need to sign the message by x509 certificate (no Encryption).
(As per your article, I am using ProtectionLevel = System.Net.Security.ProtectionLevel.Sign )


As per your article following my binding :













Till now I been able to navigate through various issues with help of various posts but I have hit a dead end.


Regards
Tushar

Yaron Naveh (MVP) said...

Hi Tushar

Xml is not seen well in post comments, so please send me a mail with the problem details.

sss said...

Yaron,
Great knowledgebase.
I am getting this error
Evaluating signature reference '_1'
Current XPath expression '/*[local-name()='Envelope']/*[local-name()='Body']' covered by signature

'Extracted the certificate chain from the BinarySecurityToken having format x509'
Reject set: Hash values do not match.

Yaron Naveh (MVP) said...

hi sss

I need more information such as a sample working soap, the one you actually send, and your config.

dp said...

Thanks Yaron,
Your blog on WCF security is excellent. Lately I had to incorporate mutual certificate authentication between WCF4.0 and Oracle API Gateway 11.1.2
We came across a lot of issues for which I referred to your blog and your answers in many other forums.
Finally I came across this exception
System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.

Using the information on your blog I was able to write a custom encoder and edit the response to remove the header information.

But one thing did not make sense to me which is that I have used AsymmetricSecurityBindingElement whereas the oracle service uses SymmetricSecurity and still my code below works

AsymmetricSecurityBindingElement asymmsecurityBindingElement = new AsymmetricSecurityBindingElement();
X509SecurityTokenParameters initiator = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.RawDataKeyIdentifier, SecurityTokenInclusionMode.AlwaysToRecipient);
X509SecurityTokenParameters recipient = new X509SecurityTokenParameters(X509KeyIdentifierClauseType.RawDataKeyIdentifier, SecurityTokenInclusionMode.AlwaysToInitiator);
asymmsecurityBindingElement.InitiatorTokenParameters = initiator;
asymmsecurityBindingElement.RecipientTokenParameters = recipient;
asymmsecurityBindingElement.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
asymmsecurityBindingElement.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;
asymmsecurityBindingElement.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
asymmsecurityBindingElement.DefaultAlgorithmSuite = System.ServiceModel.Security.SecurityAlgorithmSuite.Basic256Rsa15;
asymmsecurityBindingElement.EnableUnsecuredResponse = true;

Yaron keep up the good work.
Thanks again.

Yaron Naveh (MVP) said...

Hi DP

Since Oracle uses anotehr library than WCF than possibly what they call symmetric key is similar to WCF asymmetric config since the altetr internally also use a symmetric key, and the assymetric one is just used as a wrapper.

Unknown said...

Hi Yaron,

I have the same issue. In your scenario you use the service certificate as clientcredentials. I have a client and a service certifcate. See below.
I also use ProtectionLevel.Sign.

My question. Is my scenario different from what you describe? So does the client certificate matter?








Yaron Naveh (MVP) said...

Hi Rene

As long as you only sign the message and not encrypt it, you are in the same use case as the blog post. One option is that you were provided with a wrong server certificate. Check the server response it usually contains the real certificate base64 encoded inside it. You could extract it, save it as binary with .cer extension, and configure it as the real server certificate.

Unknown said...

Check the server response it usually contains the real certificate base64 encoded inside it. You could extract it, save it as binary with .cer extension, and configure it as the real server certificate.

But how to do it?

Yaron Naveh (MVP) said...

first check the server response (using Fiddler or WCF logging) and search on the XML for a tag called "binarySecurityToken". It contains the base64 value of the certificate. then use Convert.FromBase64 to get the certificate bytes which you can save to disk to a .cer file with File.WriteAllBytes.

Unknown said...

Thanx a lot. It is realy help!

Shankar said...

Error on client side is "The identity check failed for the outgoing message. The expected identity is 'identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint)' for the 'http://10.196.1.39/WebService-Ws20007Federadtion/Service1.svc/calc/asymm".
I have mailed you details descr.Please help

Shankar said...

Hi Yaronn,

I have been reading your post.It really helpful.

I am stuck in WCF service.

I have started with HELLoWORLd.I have done so far is creating X509 certifications using Makecert,two certifcates.One for service and one for client.Certificates are exchanged in both side

I have hosted Service in One IIS and also client in another machine but runs in locally not yet hosted in IIS.It sworking but you know my manager told me change the concept now saying

A message must contain a SAML2 Bearer Token representing the credentials on behalf of which the request is made (Principal), must be digitally signed by a key representing the (web) application issuing the request (Requestor), must be encrypted with the service certificate. Responses are in turn signed with the Service key, and encrypted with the Requestor certificate

Hence this the enumeration of the policy enforcement points to establish a secure message exchange:

1. A SAML2 Bearer token signed by an issuer that ServicePoject Trust
2. A Digital Signature for an approved Requestor (for the specific service)
3. A message encrypted with a ServicePoject certificate for the service being invoked

Symmetrically the responses will have the following controls:

1. Signed with a ServicePoject Key for the service being invoked
2. Encrypted with the Requestor Key.

Hope you have understood what i am looking for .



So what I did was downloaded http://download.microsoft.com/download/1/5/9/159D6D71-7728-45D4-BC15-5DF1F2DDCD94/WF_WCF_Samples.exe.
Inside this extensiblity==>samltokenprovider.I copied code to service =>web.config





























































































































































And client added service certificates in trusted people folder web.config



































Yaron Naveh (MVP) said...

Hi Shankar

You have identity tags in your config with certificates hard coded in them. If you are using different certificates than the sample this may cause the error. I suggest for start you set up the sample exactly as is (including certificate) and not just copy the config to your project. Than when you learn how the sample work you can migrate it.

Unknown said...

Hi Yaron!

I have a problem in a mutual authentication with x509 certificates, i really appreciate if you can check it:

https://social.msdn.microsoft.com/Forums/vstudio/en-US/c835f6b1-cc44-4230-91b0-dba30797ae9c/wcf-securechannel-we-have-userprovided-certificates-the-server-has-not-specified-any-issuers-so?forum=wcf&prof=required

Thanks

Yaron Naveh (MVP) said...

Hi Camilo

Glad to see you solved it

ab said...

What could it possibly mean if I am receiving the same error message, but the binary security token isn't returned in the response? Is the server possibly misconfigured, is this done by design, or for some other reason?

Yaron Naveh (MVP) said...

possibly the server certificate is references in the response message by other means such as a KeyInfo clause.

Anonymous said...

Hi i have the same error... The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected...

This is my custom binding and configuration endpoint:


Uri httpUri = new Uri("myUri");
EndpointAddress endPoint = new EndpointAddress(httpUri, EndpointIdentity.CreateDnsIdentity("My DNS"));

ServiceReference2.RecibirResultadoInspeccionIcaWSClient cliente = new ServiceReference2.RecibirResultadoInspeccionIcaWSClient(this.GetCustomBinding(), endPoint);

cliente.Endpoint.Contract.ProtectionLevel = ProtectionLevel.EncryptAndSign;
cliente.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

cliente.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySerialNumber, "ServiceCertificate");
cliente.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySerialNumber, "ClientCertificate");

cliente.Open();

infoResultadoInspeccionSal resultadoexpo = cliente.registrarResultadoInspeccion(envio);

CustomBinding

AsymmetricSecurityBindingElement asbe = (AsymmetricSecurityBindingElement)SecurityBindingElement.CreateMutualCertificateDuplexBindingElement();
asbe.MessageSecurityVersion = MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;

asbe.InitiatorTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never, RequireDerivedKeys = true};
asbe.RecipientTokenParameters = new System.ServiceModel.Security.Tokens.X509SecurityTokenParameters { InclusionMode = SecurityTokenInclusionMode.Never, RequireDerivedKeys = true};
asbe.MessageProtectionOrder = System.ServiceModel.Security.MessageProtectionOrder.SignBeforeEncrypt;

asbe.SecurityHeaderLayout = SecurityHeaderLayout.Lax;
asbe.EnableUnsecuredResponse = true;
asbe.IncludeTimestamp = false;
asbe.SetKeyDerivation(false);
asbe.AllowInsecureTransport = true;
asbe.AllowSerializedSigningTokenOnReply = true;
asbe.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic128;
asbe.LocalClientSettings.DetectReplays = false;
asbe.KeyEntropyMode = SecurityKeyEntropyMode.ClientEntropy;

// CREATE BINDING
CustomBinding myBinding = new CustomBinding();
// ADD SECURITY
myBinding.Elements.Add(asbe);
// ADD ENCODING
myBinding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8));
// ADD TRANSPORT
myBinding.Elements.Add(new HttpTransportBindingElement());

ServiceBehaviorAttribute sb = new ServiceBehaviorAttribute();

return myBinding;