2014-01-27 93 views
4

我试图通过他们的WSDL创建与Web服务的连接。我被告知服务的身份验证通过交换证书来描述为带有身份验证的TLS。我通过visual studio中的“添加服务引用”生成客户端。当我发送命令时,我希望看到线鲨中的“握手”,但我甚至没有看到发送“客户端Hello”的启动。具有相互身份验证的服务客户端(双向客户端证书身份验证)

服务的认证说明如下: http://en.wikipedia.org/wiki/Transport_Layer_Security#Description

我的客户是在C#writen

这里是我运行测试连接完整的程序(它开始运行()):

public class ClientExample 
{ 
    private const string Url = 
     "https://xxxxxxxxx"; 

    public static void Run() 
    { 
     ServicePointManager.ServerCertificateValidationCallback += ValidateCertificate; 
     ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

     PerformTest("Clear Cache", GetBinding()); 
    } 

    private static Binding GetBinding() 
    { 
     var bec = new BindingElementCollection 
      { 
       new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), 
       new HttpsTransportBindingElement{ RequireClientCertificate = true } 
      }; 
     return new CustomBinding(bec); 
    } 

    private static void PerformTest(string test, Binding binding) 
    { 
     try 
     { 
      Console.ResetColor(); 
      Console.ForegroundColor = ConsoleColor.Green; 
      Console.WriteLine(test); 
      Console.ResetColor(); 

      var client = GetClient(binding); 
      SendMessage(client); 
     } 
     catch (Exception e) 
     { 
      DisplayError(e); 
     } 
    } 

    private static MyClient GetClient(Binding binding) 
    { 
     var endpointAddress = new EndpointAddress(Url); 

     var client = new MyClient(binding, endpointAddress); 

     if (client.ClientCredentials != null) 
     { 
      client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, 
                     X509FindType.FindBySubjectName, 
                     "xxxxxxxxxxxxx");     
     } 
     return client; 
    } 

    private static void SendMessage(ChargePointServiceClient client) 
    { 
     var response = client.clearCache("xxxxxxxxxxxxx", new ClearCacheRequest()); 
     Console.WriteLine(ClearCacheDescription(response)); 
    } 

    private static string ClearCacheDescription(ClearCacheStatus response) 
    { 
     switch (response) 
     { 
      case ClearCacheStatus.Accepted: 
       return "Accepted"; 
      case ClearCacheStatus.Rejected: 
       return "Rejected"; 
     } 

     return "Unkown"; 
    } 

    private static bool ValidateCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) 
    { 
     switch (sslpolicyerrors) 
     { 
      case SslPolicyErrors.None: 
       return true; 
      case SslPolicyErrors.RemoteCertificateChainErrors: 
       DisplayWarningMessage("RemoteCertificateChainErrors"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateNameMismatch: 
       DisplayWarningMessage("RemoteCertificateNameMismatch"); 
       return false; 
      case SslPolicyErrors.RemoteCertificateNotAvailable: 
       DisplayWarningMessage("RemoteCertificateNotAvailable"); 
       return false; 
      default: 
       DisplayWarningMessage("Unkown Certificate Validation Error"); 
       return false; 
     } 
    } 

    private static void DisplayError(Exception exception) 
    { 
     if (exception == null) 
      return; 

     Console.BackgroundColor = ConsoleColor.DarkRed; 
     Console.ForegroundColor = ConsoleColor.White; 
     Console.WriteLine(@"Exception"); 
     Console.ResetColor(); 
     Console.WriteLine(exception.Message); 

     if (exception.InnerException != null) 
      Console.WriteLine(); 

     DisplayError(exception.InnerException); 
    } 

    private static void DisplayWarningMessage(string message) 
    { 
     Console.BackgroundColor = ConsoleColor.DarkYellow; 
     Console.ForegroundColor = ConsoleColor.White; 
     Console.WriteLine(message); 
     Console.ResetColor(); 
    } 
} 

我登录通过system.diagnostic所有网络流量在我的app.config:

<system.diagnostics> 
    <sources> 
    <source name="System.Net"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    <source name="System.Net.Sockets"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    <source name="System.Net.Cache"> 
     <listeners> 
     <add name="System.Net"/> 
     </listeners> 
    </source> 
    </sources> 
    <switches> 
    <add name="System.Net" value="Verbose"/> 
    <add name="System.Net.Sockets" value="Verbose"/> 
    <add name="System.Net.Cache" value="Verbose"/> 
    </switches> 
    <sharedListeners> 
    <add name="System.Net" 
     type="System.Diagnostics.TextWriterTraceListener" 
     traceOutputOptions="None" 
     initializeData="network.log" 
    /> 
    </sharedListeners> 
    <trace autoflush="true"/> 
</system.diagnostics> 

这里有一些感兴趣的日志行:

这证实了一个TLS流创建:创建

System.Net Information: 0 : [9040] TlsStream#50727427::.ctor(host=xxxxx, #certs=1) 

安全通道:

System.Net Information: 0 : [9040] SecureChannel#11159819::.ctor(hostname=xxxxxxx, #clientCertificates=1, encryptionPolicy=RequireEncryption) 
System.Net Information: 0 : [9040] Enumerating security packages: 
System.Net Information: 0 : [9040]  Negotiate 
System.Net Information: 0 : [9040]  NegoExtender 
System.Net Information: 0 : [9040]  Kerberos 
System.Net Information: 0 : [9040]  NTLM 
System.Net Information: 0 : [9040]  TSSSP 
System.Net Information: 0 : [9040]  pku2u 
System.Net Information: 0 : [9040]  Schannel 
System.Net Information: 0 : [9040]  Microsoft Unified Security Protocol Provider 
System.Net Information: 0 : [9040]  LiveSSP 
System.Net Information: 0 : [9040]  WDigest 
System.Net Information: 0 : [9040]  CREDSSP 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Attempting to restart the session using the user-provided certificate: [Version] 

不知道为什么要查找私钥:

System.Net Information: 0 : [9040] SecureChannel#11159819 - Left with 1 client certificates to choose from. 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Trying to find a matching certificate in the certificate store. 
System.Net Information: 0 : [9040] SecureChannel#11159819 - Locating the private key for the certificate: [Version] 

在此日志中,我看到证书已交换。不幸的是丝鲨并不确认这个...

现在我的程序验证的服务证书,并开始处理

System.Net Information: 0 : [9040] SecureChannel#11159819 - Remote certificate was verified as valid by the user. 
System.Net Information: 0 : [9040] ProcessAuthentication(Protocol=Ssl3, Cipher=Rc4 128 bit strength, Hash=Sha1 160 bit strength, Key Exchange=RsaKeyX 2048 bit strength). 

然后我看到了一些加密的数据交换和我清除缓存命令发送

我收到来自服务的加密响应,但消息指示出现故障。我想这是因为身份验证不是由服务

System.Net Error: 0 : [9040] Exception in HttpWebRequest#46890055::GetResponse - The remote server returned an error: (500) Internal Server Error.. 

这里接受的(包括IP地址是服务不是我)

(ip.src == xxx.xxx.xxx.xx or ip.dst == xxx.xxx.xxx.xx) and ssl.handshake 

而且,证书我使用Wireshark的中过滤器我正在使用没有私钥。我认为我不应该需要TLS文档中的一个。

所以我的问题是为什么我在运行程序时在wireshark中看不到Client Hello/Server Hello,或者应该如何配置客户端绑定以启动客户端hello?

(我标记WCF,因为我认为WCF的专业人士可能知道答案,我的问题。我的解决方案将是独立的WCF的,因为我没有服务绑定的控件)

回答

2

这听起来像你在做什么描述是在SSL/TLS中使用客户端证书认证。在这种情况下,您使用的客户端证书肯定需要一个私钥,这对于完成SSL/TLS握手是必需的。

注意配置客户端的时候,你需要告诉绑定使用客户证书进行传输认证:

<security mode="Transport"> 
    <transport clientCredentialType="Certificate" /> 
</security> 

然后告诉它如何定位证书,你想用则ClientCertificate行为,以便使用:

<behaviors> 
    <endpointBehaviors> 
    <behavior name="ClientCertificateBehavior"> 
     <clientCredentials> 
     <clientCertificate findValue="CN=clienttempcert" storeLocation="CurrentUser" 
      storeName="My" x509FindType="FindBySubjectDistinguishedName" /> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 

注意,证书指定键MUST HAVE私钥,客户端可以加载(该服务,但是,这并不需要私有密钥的话)。

+0

这是我不清楚的部分。我被告知通过浏览器下载证书,我下载的证书没有私钥。当我打开证书时,它会显示“此证书用于以下目的:*承认远程计算机的身份*将您的身份证明给远程计算机。”对我而言,我似乎只是向服务提供证书以证明身份,然后通过我提供的维基链接中描述的步骤4进行加密。 – aelstonjones

+0

我假设浏览器在访问https站点时会有相同的机制。浏览器不会拥有私钥,但通信最终会被加密。 – aelstonjones

+0

你从哪里下载证书?这是来自证书颁发机构吗?通常情况下,如果您使用证书颁发机构生成新证书,则CA不会获取或生成私钥,该私钥只在发出请求的计算机上生成,然后在您身份时将密钥与证书进行匹配将它下载回同一台机器。 – tomasr

0

获取PFX,并将其安装到服务器证书。到个人商店或当前商店,本地机商店等。

然后在asp.net web.config中使用这个并使用findbyThumbPrint。

<behaviors> 
    <endpointBehaviors> 
    <behavior name="ClientCertificateBehavior"> 
     <clientCredentials> 
     <clientCertificate findValue="yourthumprinthere" storeLocation="CurrentUser" or PersonalStore 
      storeName="My" x509FindType="FindByThumbprint" /> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors>