2014-01-27 2 views
4

Я пытаюсь создать соединение с веб-службой через их WSDL. Мне сказали, что аутентификация службы называется TLS с аутентификацией путем обмена сертификатами. Я создал клиента через «Добавить ссылку на службу» в visual studio. Когда я посылаю команду, я ожидаю увидеть «рукопожатие» в проводной акуле, но я даже не вижу инициирование инициирования «Клиент Hello».Сервисный клиент с взаимной аутентификацией (аутентификация сертификата двухстороннего клиента)

аутентификации сервиса описана здесь: http://en.wikipedia.org/wiki/Transport_Layer_Security#Description

Мой клиент прописан в C#

Вот полная программа, которую я бегу, чтобы проверить соединение (она начинается с Run()):

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> 

Вот некоторые из бревенчатых линий интерес:

Это подтверждает, что поток ДУС создан: создан

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.. 

Вот фильтр я использую в Wireshark (оба IP-адрес являются услугой не мой)

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

Кроме того, сертификат Я использую не имеет закрытого ключа. Я предполагаю, что мне не нужен один из документации TLS.

Итак, мой вопрос в том, почему я не вижу клиента Hello/Server Hello в wirehark при запуске программы или как мне настроить привязку клиента для инициации приветствия клиента?

(я меченый ФОС, потому что я предполагаю, что ФОС специалисты могли бы знать ответ на мой вопрос. Мое решение будет зависеть от ФОС, потому что у меня нет контроля над креплениями услуг)

ответ

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> 

Обратите внимание, что сертификат, указать ключ ДОЛЖНЫ частный ключ, который клиент может загрузить (услугу, однако, не нужен закрытый ключ на всех).

+0

Это часть, о которой я не знаю. Мне было сказано загрузить сертификат через браузер, а сертификат, который я загрузил, не имеет закрытого ключа. Когда я открываю сертификат, он говорит: «Этот сертификат предназначен для следующих целей: * Выдайте идентификатор удаленного компьютера. * Доказывает вашу личность на удаленном компьютере». Мне кажется, что я просто предоставляю сертификат службе для подтверждения личности, тогда шифрование происходит через шаг 4, описанный в ссылке wiki, которую я предоставил. – 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> 
Смежные вопросы