none
WCF BasicHttpBinding SSL Message Encryption RRS feed

  • Question

  • I have WCF Service hosted in IIS Server with SSL provided

    This WCF service is used inside a PCL ( Portable Class Library ) that i used for my Xamarin.Forms ( Android,IOS,Windows Phone)

    Now i connect to my service from the application .. the connection looks like this..

    https://mysite.mywebservice.com:1111/someservice.svc

    and is working very well. I can connect and request data from the service just fine..

    Recently i wanted to make sure that the connection between transportation of data are secure but for my surprise was NOT

    I have installed on my android an application called NET CAPTURE which allows you to monitor the traffic of your network data..

    When i request from my service e.g customers... and then go to NET CAPTURE to see what is shows.. i can see in XML format all the properties and the names of income data..

    I thought that by providing an SSL to the wcf service  in IIS  these information would be encrypted and i wouldn't need to do any other configuration to the wcf.

    What i do wrong ? How can i protect my data? 


    stelios ----------






    • Edited by stelios84 Wednesday, January 23, 2019 1:57 PM
    Wednesday, January 23, 2019 1:49 PM

All replies

  • Hi stelios84,
    Message security is not supported in BasicHttpBinding binding, except that both the server and client use the certificate to protect the security of the transmitted message.
    Use the certificates only ensure that transport layer security, if you don’t want to expose the message, you could use the message security which also need client to provide certificate. 
    In fact, BasicHttpBinding aims to compatible with the old web service. in a sense, the security of the message is lost. Here is the transmitted message in Wshttpbinding.

    https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-in-wcf
    Best Regards
    Abraham
    Tuesday, January 29, 2019 6:55 AM
    Moderator
  • Hi Abraham..

    I really found it difficulty to understand.

    How from the android device ( Xamarin.Forms ) i use this certificate.?

    in my WCF App.Config i have the following now :

    <security mode="Message">
      <message clientCredentialType="Certificate"/>
    </security>


    <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <dataContractSerializer maxItemsInObjectGraph="2147483647"/> <serviceDebug includeExceptionDetailInFaults="false"/>

    <serviceCredentials> <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/> </serviceCredentials> </behavior>

    and in android device  i have 

        Private Sub Login()
            Dim MyService As New ServiceReference1.Service1Client
            AddHandler MyService.GetItemsAsync, AddressOf GetItemsCompleted_
            MyService.GetItemsAsync()
    
        End Sub

    but i still see the xml schema in fiddler let's say.. ( or any other application that can encrypt ssl)


    stelios ----------

    Monday, February 4, 2019 10:15 AM
  • Hi stelios84,
    As far as I know, the client proxy class have some methods to set up the client certificate.
    First you should set up the certificate/get the certificate file in the local machine. 

    Besides, as I've shown in the screenshot, you can use WSHttpBinding to encrypt communication and server username password to encrypt message security.
    Best Regards
    Abraham
    Friday, February 8, 2019 8:44 AM
    Moderator
  • Hi , Unfortunate i do not have this options available as am using Portable Class Library

    Also i cannot use WSHttpBinding as  xamarin.forms supports only BasicHttpBinding With TransportSecurity Only

    

    I think my only option is to encrypt the xml request 

    I try to use TripleDESCryptoServiceProvider before send to service and or to client but fails every time i change the message e.g from xml to encoded characters (i guess because the server fails to recognize the schema )

    I have implement IClientMessageInspector at the client Side as also IDispatchMessageInspector at the server side.

    events from IDispatchMessageInspector

    • BeforeSendReply
    • AfterReceiveRequest

    And events from IClientMessageInspector

    • AfterReceiveReply
    • BeforeSendRequest

    are fire just fine if i do not touch the message

    I need some help how i can send the xml request encrypted to the server 

    Just to show a small portion of what i have at client side

    Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
    
        Dim Binding As New BasicHttpBinding(BasicHttpSecurityMode.Transport)
    
        Dim ms As MemoryStream = New MemoryStream(System.Text.Encoding.UTF8.GetBytes(EncryptedData(request.ToString)))
    
        Dim RQuotas As Xml.XmlDictionaryReaderQuotas = Binding.ReaderQuotas
    
        Dim reader = Xml.XmlDictionaryReader.CreateTextReader(ms, RQuotas)
        request = Message.CreateMessage(reader, Int32.MaxValue, request.Version)
    
    
        Return Nothing
    
    End Function

    But every time try to encrypt and send it i receive an exception (the server not event respond to event) so i guess most probably the service not recognise the schema and reject it right away and not even go to the wire for send.


    stelios ----------







    • Edited by stelios84 Friday, February 8, 2019 1:08 PM
    Friday, February 8, 2019 12:47 PM
  • Hi stelios84,
    Don’t use the message inspector to modify the message body, it could cause message content validation to fail, breaking the integrity of the message, which is determined by many server factors, such as binding type, encryption and compression mode, service namespace. In fact, DotNet has provided the another solution, Message Formatter, which allowed developers to customize the message content.
    https://docs.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-message-formatters
    https://blogs.msdn.microsoft.com/carlosfigueira/2011/05/02/wcf-extensibility-message-formatters/
    I have made a demo, wish it is useful to you.
    Server side.

    class Program
        {
            static void Main(string[] args)
            {
                Uri uri = new Uri("http://localhost:1123");
                BasicHttpBinding binding= new BasicHttpBinding();
                binding.Security.Mode = BasicHttpSecurityMode.None;
                using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
                {
                    sh.AddServiceEndpoint(typeof(IService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb==null)
                    {
                        smb = new ServiceMetadataBehavior();
                        sh.Description.Behaviors.Add(smb);
                    }
                    Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
                    sh.Opened += delegate
                    {
                        Console.WriteLine("Service is ready");
                    };
                    sh.Closed += delegate
                    {
                        Console.WriteLine("Service is closed");
                    };
                    sh.Open();
                    Console.ReadLine();
                    sh.Close();
                    
                }
            }
        }
        [ServiceContract]
        [MyContractBehavior]
        public interface IService
        {
            [OperationContract]
            int Add(int a, int b);
        }
        public class MyService : IService
        {
            public int Add(int a, int b)
            {
                return a + b;
            }
        }
        public class MyServerFormatter : IDispatchMessageFormatter
        {
            DispatchOperation opt=null;
            public MyServerFormatter(DispatchOperation op)
            {
                opt = op;
            }
    
            public void DeserializeRequest(Message message, object[] parameters)
            {
                byte[] data = message.GetBody<byte[]>();
                int a = BitConverter.ToInt32(data, 0);
                int b = BitConverter.ToInt32(data, sizeof(int));
                parameters[0] = a;
                parameters[1] = b;
            }
    
            public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
            {
                byte[] data = BitConverter.GetBytes((int)result);
                return Message.CreateMessage(messageVersion, opt.ReplyAction, data);
            }
        }
    
        public class MyOperationBehavior : IOperationBehavior
        {
            public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
            {
                return;
            }
    
            public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
            {
                return;
            }
    
            public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
            {
                dispatchOperation.Formatter = new MyServerFormatter(dispatchOperation);
            }
    
            public void Validate(OperationDescription operationDescription)
            {
                return;
            }
        }
        [AttributeUsage(AttributeTargets.Interface,AllowMultiple =false)]
        public class MyContractBehaviorAttribute : Attribute, IContractBehavior
        {
            public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                return;
            }
    
            public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                return;
            }
    
            public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
            {
                OperationDescription op = contractDescription.Operations[0];
                op.Behaviors.Add(new MyOperationBehavior());
            }
    
            public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
            {
                return;
            }
        }
    


    Client side.(don’t forget to apply the MyContractBehavior to auto-generated service interface)

        class Program
        {
            static void Main(string[] args)
            {
                ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
                try
                {
                    var result = client.Add(234, 34);
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
        public class MyClientFormatter : IClientMessageFormatter
        {
            ClientOperation _co = null;
            public MyClientFormatter(ClientOperation co)
            {
                _co = co;
            }
            public object DeserializeReply(Message message, object[] parameters)
            {
                byte[] data = message.GetBody<byte[]>();
                int res = BitConverter.ToInt32(data, 0);
                
                return res;
            }
    
            public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
            {
                byte[] data = null;
                byte[] buffer1 = BitConverter.GetBytes((int)parameters[0]);
                byte[] buffer2 = BitConverter.GetBytes((int)parameters[1]);
                data = new byte[buffer1.Length + buffer2.Length];
                Array.Copy(buffer1, 0, data, 0, buffer1.Length);
                Array.Copy(buffer2, 0, data, buffer1.Length, buffer2.Length);
                return Message.CreateMessage(messageVersion, _co.Action, data);
            }
        }
    
        public class MyOperationBehavior : IOperationBehavior
        {
            public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
            {
                return;
            }
    
            public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
            {
                clientOperation.Formatter = new MyClientFormatter(clientOperation);
            }
    
            public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
            {
                return;
            }
    
            public void Validate(OperationDescription operationDescription)
            {
                return;
            }
        }
        [AttributeUsage(AttributeTargets.Interface, AllowMultiple = false)]
        public class MyContractBehaviorAttribute : Attribute, IContractBehavior
        {
            public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                return;
            }
    
            public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                OperationDescription od = contractDescription.Operations[0];
                od.OperationBehaviors.Add(new MyOperationBehavior());
            }
    
            public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
            {
                return;
            }
    
            public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
            {
                return;
            }
    }
    

    Result(before applying the extension)

    Result(after applying the extension)

    Also please see the following advice, I think it is useful to you.
    1. Xamarin does not support the Visual Basic.NET language.
    https://docs.microsoft.com/en-us/xamarin/cross-platform/platform/visual-basic/xamarin-forms
    2. As mentioned in all Microsoft document. Portable class libraries have been deprecated in the latest version of visual studio, and .Net Standard Libraries are recommended instead
    https://docs.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/pcl?tabs=windows
    3. the API which implements the client set up the certificate is available when I changed the project template (VB class library PCL) to C# class library(.net standard).

    Feel free to let me know if there is anything I can help with.

    Best Regards

    Abraham

    Tuesday, February 19, 2019 9:54 AM
    Moderator