【问题标题】:Encryption/Decryption with SIP TLS使用 SIP TLS 加密/解密
【发布时间】:2014-02-04 15:31:07
【问题描述】:

在我的 SIP Sorcery 项目中,我正在创建一个到远程服务器的 TLS 连接,并由远程服务器提供证书提供程序。 使用以下代码 sn-p 连接似乎很好:

    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");
    }

但是我很困惑如何创建私钥来加密/解密在客户端和服务器之间发送的数据?我可以看到 cert.PublicKey 不为空。我正在接收一些应用程序数据,但由于我无法在没有私钥的情况下对其进行解密,所以我看不到客户端和服务器之间出现了什么问题...

【问题讨论】:

  • 您是否独立于 TLS 进行加密?
  • @PeterRitchie 正如 sipwiz 指出的那样,SIP Sorcery 中的 TLS 封装处理加密/解密。所以我想我的实际问题是如何获得匹配的私钥/公钥值对。
  • 如果 TLS 进行加密/解密,你需要密钥做什么?

标签: c# encryption sip x509certificate2


【解决方案1】:

无需创建任何额外的加密密钥。 TLS 连接将对连接上发送的任何数据进行加密和解密。如果您进行wireshark 跟踪,您将能够看到TLS 握手,之后所有后续数据包基本上都是随机字节。

为了使 SIP TLS 通道能够操作您传递给它的文件或证书存储名称,必须包含或可访问私钥。从示例的外观来看,如果您提供 .cer 文件,则很可能没有可用的私钥,并且 SIP TLS 通道将无法初始化。通常,您需要一个 .pfx 或等效文件,将证书与私钥结合使用。

此外,在发送调用中,您不会传递文件 ptah,而是应该传递您将为远程服务器证书接受的名称。然后,SIP TLS 通道会将远程服务器提供的证书名称与您准备接受的证书名称相匹配。

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

更新

我在下面的其中一个 cmets 中略有错误,因为只有当客户端尝试连接时 SIPTLSChannel 上没有可用的私钥时才会引发异常。如果您只打算将 SIPTLSChannel 用于传出连接,那么您不需要私钥(除非另一端的服务器正在使用证书对您进行身份验证,这在 SIP 世界中是不常见的)。

关于从 SIPTLSChannel 中获取解密数据的原始问题,正如我最初提到的那样,这一切都发生在幕后。下面是建立与 SIP TLS 服务器(在本例中为 sipsorcery.com)的连接并读取响应的示例。来自服务器的传输请求和响应都通过加密的 TLS 通道进行传输,您可以使用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());
        }
    }
}

如果您想生成自己的证书和私钥,这个关于设置MySQL certificates 的页面是一个很好的指南。

您可以通过使用浏览器连接到 TLS 通道正在使用的套接字来测试您的证书是否具有可用于客户端连接的私钥,例如在上述示例中,我使用https://myipaddress.com:5061

【讨论】:

  • 所以send方法中的字符串参数是远程服务器的dns,还是.cer文件中的名称??如何获取 .pfx 或等效密钥文件?在我的系统中还没有真正使用过 priv/pub 密钥。我的计算机上有一个 .cer 文件,并且已将其安装在我的计算机上,因此它在 windows 的证书管理器中进行计算。我可以在 WS 中看到握手会话,并且我看到在协商之后,我正在发送一个加密的应用程序数据,但是没有发生任何事情,可能是因为我向服务器发送了错误的内容。但我无法在没有密钥的情况下对应用数据进行解密。
  • 发送方法字符串参数需要是服务器提供的TLS证书的Common Name。 sipsorcery TLS 通道甚至不应该在没有私钥的情况下初始化,所以我猜你必须有一个。您希望在哪里解密数据?您不能手动完成,TLS 解密都发生在 .Net 加密流的幕后。
  • 我希望我可以导出密钥,以解密 Wireshark 中跟踪的数据,但这仅用于调试。我应该在我的 sip 应用程序(SIPResponseReceived 事件)中使用解密,并在服务器和客户端之间来回传递信号。如果我对代码 sn-p 执行 cert.PrivateKey,它会返回 null。有什么方法可以检查这个 PK 是否有首字母缩写?如果我查看我的 mmc.exe,还没有将任何密钥绑定到导入的证书,我不确定是我应该制造 PK 和/或公钥,还是服务器应该提供给我的东西?
  • 您可以在记事本中打开 .cer 文件,查看是否包含私钥。该文件应该是 base64 编码的,并且有两个不同的部分,一个用于证书,一个用于私钥。除此之外,openssl 是处理证书和私钥的最佳工具。您是如何在 myCa.cer 文件中生成证书的?
  • .cer 文件里面只有一个 BEGIN 和 END 证书。它被编码为base64。 .cer 文件是从我的服务器提供商生成的。
猜你喜欢
  • 2018-12-31
  • 2014-07-03
  • 2020-09-30
  • 2016-03-05
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多