5

I have a multi threaded async System.Net.Socket which listens on a port. I don't have any problem if I get a request from HTTP, but recently I had to add https support to my application.

The client gave me an .arm certification file. It has base-64 encoded ASCII data in it. The file name is cert.arm and it is stored in the root of my solution folder.

Here is what I do till now to use that certificate:

using System;
using System.Net;
using System.Threading;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace SocketExample
{
    public class StackOverFlow
    {
        public static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
        private static X509Certificate2 _cert = X509Certificate2("..\\..\\cert.arm");

        static void Main(string[] args)
        {
            StartListening();
        }

        private static void StartListening()
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 9002);

            if (localEndPoint != null)
            {
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                if (listener != null)
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(10);

                    Console.WriteLine("Socket listener is running...");

                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                }
            }
        }

        private static void AcceptCallback(IAsyncResult ar)
        {
            _manualResetEvent.Set();

            Socket listener = (Socket)ar.AsyncState;

            Socket handler = listener.EndAccept(ar);

            SslStream sslStream = new SslStream(new NetworkStream(handler, false));
            sslStream.AuthenticateAsServer(_cert); // I get exception on this line

            StateObject state = new StateObject();
            state.workSocket = handler;

            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        }

        private static void ReceiveCallback(IAsyncResult result)
        {
            StateObject state = (StateObject)result.AsyncState;
            Socket handler = state.workSocket;

            int numBytesReceived = handler.EndReceive(result);

            if (!handler.Connected)
            {
                handler.Close();
                return;
            }

            if (numBytesReceived > 0)
            {
                state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, numBytesReceived));

                string[] lines = state.sb.ToString().Split('\n');

                if (lines[lines.Length - 1] == "EOF")
                {
                    // All Data Received. Do Something.
                }
                else
                {
                    // All Data is not received. Continue reading...
                    handler.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
                }
            }
        }
    }
}

Certification file is created successfully. I can see the data in _cert variable. It is OK.

The problem is that when I call the AuthenticateAsServer method I get NotSupportedException which says: "The server mode SSL must use a certificate with the associated private key".

How can I apply this certification file to my socket?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Orkun Bekar
  • 1,447
  • 1
  • 15
  • 36
  • Is your service reachable over the open Internet? Do your clients access it by DNS name or IP address? If by DNS name, do you own or adminster the domain? – Jeffrey Hantin Apr 27 '15 at 22:28

1 Answers1

2

You should probably use X509Certificate2 instead of X509Certificate. It could be the only step required to resolve this error.

X509Certificate2 has a member for the private key, unlike X509Certificate, and the SSL socket needs the private key to do its job.

Community
  • 1
  • 1
Roman Starkov
  • 59,298
  • 38
  • 251
  • 324
  • It seems right. I'm searching for using private key now. – Orkun Bekar Apr 26 '15 at 14:24
  • cert file which is created by X509Certificate2 has no private key. Probably the problem is that. – Orkun Bekar Apr 26 '15 at 15:23
  • @OrkunBekar Yes, sounds like it. You can check by looking inside it: [here](http://stackoverflow.com/q/7400500/33080) is what it would look like if the file actually has the private key in it. It might not. Note that [.arm is the same as .pem](http://serverfault.com/a/312358/14642) (though I doubt renaming the file will make any difference in your case). – Roman Starkov Apr 26 '15 at 16:30
  • Yes, I renamed it and it still works but it does not have private key. – Orkun Bekar Apr 26 '15 at 16:59