Проблема с C # Websocket и ECDHE шифрами - PullRequest
1 голос
/ 03 октября 2019

Во-первых, я не специалист по криптозащите, поэтому я копался в новой территории.

У меня есть клиент C #, который использует веб-сокеты для получения информации от веб-службы, работающей в Tomcat. Наша текущая среда выглядит следующим образом:

Рабочие станции, на которых работает клиент - Windows 10 с .NET 4.6.2 Tomcat Server - Windows Server 2016 под управлением Tomcat 9.0.22 и OpenJDK 11.0.2 (хотя я пробовал OpenJDK 13 ита же проблема)

Tomcat настроен со следующей конфигурацией SSL:

<Connector port="8443" maxHttpHeaderSize="65536"
               allowUnsafeLegacyRenegotiation="false" 
               maxThreads="1000" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" disableUploadTimeout="true"
               acceptCount="100" connectionTimeout="20000"
               scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               SSLEnabled="true" protocol="org.apache.coyote.http11.Http11NioProtocol"
               sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation" 
               sslEnabledProtocols="TLSv1.2"
               keystoreType="Windows-ROOT" 
               keystoreFile="Running.txt" 
               ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,
                    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                    TLS_RSA_WITH_AES_128_CBC_SHA256,
                    TLS_RSA_WITH_AES_128_GCM_SHA256,
                    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
                    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                    TLS_RSA_WITH_AES_256_CBC_SHA,
                    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                    TLS_RSA_WITH_AES_256_CBC_SHA256,
                    TLS_RSA_WITH_AES_256_GCM_SHA384,
                    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
                    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
                    SSL_RSA_WITH_RC4_128_MD5,
                    SSL_RSA_WITH_RC4_128_SHA,
                    TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                    SSL_RSA_WITH_3DES_EDE_CBC_SHA"/>

Таким образом, наши сертификаты хранятся в доверенном хранилище Windows.

Мой код клиента C # с использованием веб-сокетовэто следующее:

WebSocketSharp.WebSocket ws = new WebSocketSharp.WebSocket(connectURL);
ws.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12;
ws.Connect();

и я также попробовал базовый .NET ClientWebSocket:

ClientWebSocket newWs = new ClientWebSocket();
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
                newWs.Options.AddSubProtocol("Tls12");
                try
                {
                    await newWs.ConnectAsync(new Uri(connectURL), CancellationToken.None);
                }
                catch (Exception wse)
                {
                    log.Error("Error in ClientWebSocket: " + wse.Message, wse);
                }

Оба клиента (я считаю, что WebSocketSharp - это просто удобная оболочка для базовых классов),из-за наличия объекта групповой политики на всех наших компьютерах в нашей среде отправляют только ECDHE / DHE-шифры в клиентском квитировании.

В результате отладки SSL я получаю следующую ошибку при попытке "Произвести квитирование серверного сертификата серверасообщение ":

javax.net.ssl|ERROR|33|https-jsse-nio-443-exec-2|2019-10-02 16:56:50.058 UTC|TransportContext.java:313|Fatal (INTERNAL_ERROR): Failed to sign ecdhe parameters: RSA (
"throwable" : {
  java.security.SignatureException: Keyset does not exist

    at jdk.crypto.mscapi/sun.security.mscapi.RSASignature.signHash(Native Method)

Дело в том, что

  1. Google Chrome использует точно такой же шифр (" TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xC030) ") и отлично соединяется
  2. До сертификатов Windows-ROOT у нас были серверные сертификаты (которые были сгенерированы из внешнего ЦС), хранящиеся в хранилище ключей Java, и все это прекрасно работает, если я укажунаш Tomcat к этому.

Так что мой вопрос в том, имеет ли это какое-то отношение к тому, как генерируются наши сертификаты (сейчас мы используем внутренний CA для их генерации), возможно, флаг или расширение илинемного что нужно перевернуть? Я склонялся к этому, пока не обнаружил, что у Google Chrome нет проблем с тем же шифром. Хотя рукопожатие клиента C # и рукопожатие клиента Google Chrome выглядят несколько иначе (я могу опубликовать их, если это поможет).

Я бы предположил, что в сертификате все будет правильно настроено для рукопожатий ECDHE / DHE, иначе Chrome тоже потерпит неудачу. Но тот факт, что клиент C # не имеет проблем со старыми сертификатами, заставляет меня поверить, что что-то в поколении сертификатов вызывает проблему.

Или, возможно, это комбинация обоих?

Когда япопросил нашего системного администратора добавить обратно следующие шифры TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_CBC_SHA256 TLS_RSA_WITH_AES_128 * * * *1036*

У нас есть пара человек в нашей программе, которые достаточно уверены в криптографии, генерации сертификатов и т. Д., Но они немного озадачены, поэтому любая помощь, по крайней мере, в том, где мы можем выглядеть, будет хорошей. Я полагаю, что мы можем получить отказ, разрешающий шифрование TLS_RSA, но, поскольку рукопожатия ECDHE / DHE обеспечивают более высокий уровень безопасности, было бы очень приятно выяснить, где происходит сбой и как его исправить. Я только что исчерпал свои знания в этой области.

Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...