none
C++语言开发的基于.netFramework4.6客户端软件,从证明书局(CA局)成功取得证书后,与服务端(数据收集中心Center)进行https双向认证通信时失败问题的咨询 RRS feed

  • 问题

  • C++语言开发的基于.netFramework4.6客户端软件,需要从证明书局(CA局)成功取得证书并与服务端(数据收集中心Center)进行https双向认证通信。

     但是,客户端软件从证明书局成功取得证书后,使用HttpWebRequest的函数GetResponse()与服务端(数据收集中心Center)进行HTTPS双向认证通信时通信失败。

     调查发现,在客户端与服务端进行通信握手时,客户端收到了服务端的证书后,客户端向服务端发出的证书的Length0字节。



     HttpWebRequest的函数GetResponse()使用方法如下:

     ---------------
    String ^serverUrl = gcnew String("https://*******************"); 

     HttpWebRequest ^req = dynamic_cast<HttpWebRequest
    ^>(WebRequest::Create("serverUrl));

     req->ClientCertificates->Add(epCert->GetCertificate());

     客户端软件从证明书局成功取得证书。

     System::Net::WebProxy ^proxy = attributes.channelCollection->GetProxy();

     if (proxy != nullptr)

        req->Proxy = proxy;

     HttpWebResponse ^res = dynamic_cast<HttpWebResponse
    ^>(req->GetResponse());

      调查发现,req->GetResponse执行到【通信握手过程】的第4步时,客户端向服务端发出的证书的Length0字节,之后的通信就失败了,系统抛出下面的异常。

        System.Net.WebException: The request was aborted: Could not create
    SSL/TLS secure channel.

        at System.Net.HttpWebRequest. GetResponse()

     
       at EPLAN.IEPLAN.Ping()

    -----------------

    【通信握手过程】

     1   Client > Server:
     Client Hello

     2   Server> Client :  Server Hello

     3   Server> Client :  Certificate, Certificate Request,
    Server Hello Done

     4   Client > Server:  Certificate, Client Key Exchange,
    Certificate Verify, Change Cipher Spec, Encrypted Handshake Message

     5   Server> Client : Change Cipher Spec, Encrypted Handshake
    Message(
    出错时: Alert (Level: Fatal, Description: Handshake Failure))



    C++语言开发的基于.netFramework3.5客户端软件,从证明书局(CA局)成功取得证书,并与服务端(数据收集中心Center)进行https双向认证通信不存在上述问题。

     .netFramework3.5客户端软件通信时和.netFramework4.6客户端软件具有下面的相同点:

      ・证明书局(CA局)和服务端(数据收集中心Center)相同。

      ・通信函数的调用方法完全一致,如上述代码。

      ・两者使用的加密套接字相同,都是TLS_RSA_WITH_AES_128_CBC_SHA(0x002f)

      ・【通信握手过程】的前三步通信数据一致(从第四步开始才有差异)



    对于.netFramework4.6客户端软件和服务端通信时在如下代码调用后失败的问题,能否给出解决方案或者建议?

     HttpWebResponse ^res = dynamic_cast<HttpWebResponse
    ^>(req->GetResponse());
    2017年8月29日 10:51

答案

  • Hi

    感谢你的回复。

    后面经过调查找到了这个问题的原因和解决方法。

    .netFramework3.5升级到.netFramework4.6后,向证书颁发局取得证书前需要给CspKeyContainerInfo.CspParameters.KeyContainerName指定一个唯一的值。

    否则.netFramework4.6里面向取得的证书向文字列导出时会发现CspKeyContainerInfo.CspParameters.KeyContainerName是空的,进而导致后面和服务端(数据收集中心Center)进行https双向认证通信时失败的问题。

    • 已标记为答案 柴小宝 2018年1月4日 4:00
    2018年1月4日 3:53

全部回复

  • 如上面所说,

    对于.netFramework4.6客户端软件和服务端通信时在如下代码调用后失败的问题,哪位高手能否给出解决方案或者建议?

     HttpWebResponse ^res = dynamic_cast<HttpWebResponse
    ^>(req->GetResponse());

    2017年8月31日 4:13
  • Hi,

    感谢你在MSDN论坛发帖。

    你能告诉我你的工程是什么类型,asp.net 还是winform类型?

    你有没有得到什么错误信息,这对解决问题非常有帮助。

    根据你的代码这个应该是C++ CLR的代码。  你有没有用wire shark 抓包,进行认证呢?

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年8月31日 9:47
    版主
  • 谢谢您能关注我这个问题。

    工程类型是winform。

    调查发现,req->GetResponse执行之后的通信就失败了,弹出了下面的错误信息。
          System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
        at System.Net.HttpWebRequest. GetResponse()
      
       at EPLAN.IEPLAN.Ping()

    用wire shark抓包分析过,是在调用req->GetResponse时,执行到【通信握手过程】的第4步时,客户端向服务端发出的证书的Length0字节,然后第五步爆出 Alert (Level: Fatal, Description: Handshake Failure))

    【通信握手过程】
    1   Client > Server:
     Client Hello
    2   Server> Client :  Server Hello
    3   Server> Client :  Certificate, Certificate Request,
    Server Hello Done
    4   Client > Server:  Certificate, Client Key Exchange,
    Certificate Verify, Change Cipher Spec, Encrypted Handshake Message

    5   Server> Client : Change Cipher Spec, Encrypted Handshake
    Message(
    出错时: Alert (Level: Fatal, Description: Handshake Failure))升级前的应用程序基于.netFramework3.5客户端软件,从相同的证明书局(CA局)成功取得证书,并与服务端(数据收集中心Center)进行https双向认证通信不存在上述问题。

    我们比较过截包的内容,【通信握手过程】的前三部,.netFramework3.5客户端软件和Server通信的数据内容 和 .netFramework3.6客户端软件和Server通信的数据内容 基本相同。

    目前有两个怀疑点:

    1.从.netFramework3.5升级到.netFramework4.6后,上述代码中HttpWebRequest的函数GetResponse()的调用方法是否有问题?有没有什么.netFramework3.5不需要设定的属性到了.netFramework4.6就需要设定了。

    2.【通信握手过程】的第第三步Server> Client发送证书时,Client这边要那自己本地的证书和Server传过来的证书进行验证,这个过程中.netFramework4.6与.netFramework3.5的验证相比有什么不同点导致的证书的验证失败,进而出现Client向Server发送出去的证书为0字节。

    但是调查了好久还是没能找到原因。

    2017年9月1日 10:27
  • Hi,

    感谢你的详细的反馈。

    根据你的描述你当前的工程在.NET 3.5上面没有出现现在的问题吗? 如果是这样我建议你去connect 上面提交bug。

    我比较MSDN的文档上面这个两个版本的函数,没有什么不一样的。

    HttpWebRequest.GetResponse Method 3.5

    HttpWebRequest.GetResponse Method 4.6 

    这边发现相似的问题,希望对你能有所帮助。

    HttpWebRequest call to GetResponse, fails using .net 4.5 but passes using net 4.6 

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年9月4日 8:16
    版主
  • Hi

    感谢你的回复。

    后面经过调查找到了这个问题的原因和解决方法。

    .netFramework3.5升级到.netFramework4.6后,向证书颁发局取得证书前需要给CspKeyContainerInfo.CspParameters.KeyContainerName指定一个唯一的值。

    否则.netFramework4.6里面向取得的证书向文字列导出时会发现CspKeyContainerInfo.CspParameters.KeyContainerName是空的,进而导致后面和服务端(数据收集中心Center)进行https双向认证通信时失败的问题。

    • 已标记为答案 柴小宝 2018年1月4日 4:00
    2018年1月4日 3:53