Domanda

In my SIP Sorcery project I'm creating a TLS connection to my remote server, with a certificate provider by the remote server. The connection seems fine with following code snippet:

    static SIPTLSChannel channel_tls;
    static IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("1.2.3.4"), 5061);
    static IPEndPoint localEndPoint= new IPEndPoint(IPAddress.Parse("10.0.0.1"), 8080);

    static void Main(string[] args)
    {
        //Certificate file path
        string Certificate = Environment.CurrentDirectory + @"\Certificate\myCa.cer";

        // Load the certificate into an X509Certificate object.
        X509Certificate2 cert = new X509Certificate2(Certificate);

        //TLS Channel connection
        channel_Tls = new SIPTLSChannel(cert, localEndPoint);
        Transport.RemoveSIPChannel(channel_Tcp);
        Transport.AddSIPChannel(channel_Tls);

        SIPRequest subscribe = new SIPRequest();
        .... [setting subscribe parameters] ....

        channel_Tls.Send(remoteEP, Encoding.UTF8.GetBytes(subscribe.ToString()), "myCa.cer");
    }

But I'm struggled on how do I create a Private key for en-/decryption of my data sent between client and server?? I can see that the cert.PublicKey isn't empty. I'm receiving some application data, but since I can't decrypt it without a private key, then I can't see what goes wrong between my client and server...

È stato utile?

Soluzione

There's no need to create any additional encryption keys. The TLS connection will encrypt and decrypt any data sent on the connection. If you do a wireshark trace you will be able to see the TLS handshake after which all subsequent packets will essentially be random bytes.

In order for the SIP TLS channel to be able to operate the file or certificate store name you pass to it MUST have a private key included or accessible. From the looks of your sample if you are providing a .cer file then more than likely there is no private key available and the SIP TLS channel will fail to initialise. Typically you need a .pfx or equivalent file that couples the ceritifcate to use with the private key.

Also on the Send call you don't pass in a file ptah and instead you should be passing the name you will accept for the remote server certiicate. The SIP TLS channel will then match the certificate name provided by the remote server with the one you are prepared to accept.

channel_Tls.Send(remoteEP, Encoding.UTF8.GetBytes(subscribe.ToString()), "sip.someserver.com");

Update:

I was slightly mistaken in one of the comments below in that an exception will only be thrown if there is no private key available on the SIPTLSChannel WHEN a client attempts to connect. If you are only intending to use the SIPTLSChannel for outgoing connections then you don't need a private key (unless the server at the other end is authenticating you with the certificate which would be unusual in the SIP World).

As to your original question about getting the decrypted data out of the SIPTLSChannel it's as I mentioned originally and it all happens under the hood. Below is an example of establishing a connection to a SIP TLS server (in this case sipsorcery.com) and reading the response. Both the transmitted request and response from the server are carried over an encrypted TLS channel which you can verify by using wireshark.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using SIPSorcery.Net;
using SIPSorcery.SIP;
using SIPSorcery.SIP.App;
using SIPSorcery.Sys;

namespace SIPTLS
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var sipTransport = new SIPTransport(SIPDNSManager.ResolveSIPService, new SIPTransactionEngine());
                sipTransport.SIPTransportRequestReceived += SIPRequestReceived;
                sipTransport.SIPTransportResponseReceived += SIPResponseReceived;

                X509Certificate2 cert = new X509Certificate2("test-cert.cer");
                SIPTLSChannel tlsChannel = new SIPTLSChannel(cert, new IPEndPoint(IPAddress.Any, 5061));
                sipTransport.AddSIPChannel(tlsChannel);

                var optionsReq = sipTransport.GetRequest(SIPMethodsEnum.OPTIONS, SIPURI.ParseSIPURI("sips:67.222.131.147:5061"));
                sipTransport.SendRequest(optionsReq);
            }
            catch(Exception excp)
            {
                Console.WriteLine("Exception Main. " + excp);
            }
            finally
            {
                Console.WriteLine("Press any key to exit...");
                Console.Read();
            }
        }

        private static void SIPRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest)
        {
            Console.WriteLine("SIP request received from " + remoteEndPoint + ".");
            Console.WriteLine(sipRequest.ToString());
        }

        private static void SIPResponseReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPResponse sipResponse)
        {
            Console.WriteLine("SIP response received from " + remoteEndPoint + ".");
            Console.WriteLine(sipResponse.ToString());
        }
    }
}

If you want to generate your own certificates and private keys this page on setting up MySQL certificates is a good guide.

You can test whether your certificate has a private key available for client connections by using a browser to connect to the socket the TLS channel is using, e.g. in the above samples's case I use https://myipaddress.com:5061.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top