2014-01-27 90 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>