Как цифровые сертификаты обеспечивают дополнительную безопасность поверх SSL?
В общем, я бы не сказал, что цифровые сертификаты обеспечивают «дополнительную» безопасность поверх SSL/TLS. Наоборот, они его неотъемлемая часть. Хотя подробности PKI и способы проверки сертификатов не являются частью спецификации TLS (RFC 5246) (для этого есть несколько дополнительных спецификаций, таких как RFC 5280 и RFC 6125), в самой спецификации четко упоминаются сертификаты и то, как их следует использовать.
Кажется, вы говорите о сертификатах клиента, но вы, вероятно, уже знаете о сертификатах сервера, которые встречаются гораздо чаще.
В обоих случаях цель сертификатов в SSL/TLS — аутентифицировать взаимодействующие стороны, чтобы каждая сторона могла быть уверена, что разговаривает с ожидаемой удаленной стороной.
У вас всегда должен быть как минимум сертификат сервера (иначе соединение будет уязвимо для MITM-атак). Это подтверждает личность сервера для клиента.
Кроме того, в некоторых конфигурациях клиент должен предоставить сертификат. Поскольку вы говорите о пользователях, использующих свои сертификаты из своего браузера, вы, похоже, находитесь в этой ситуации.
В этом случае дополнительная безопасность заключается в том, что клиент подвергается той же строгости аутентификации от сервера, что и сервер от клиента. В частности, поскольку закрытый ключ никогда не покидает удаленную сторону в этом процессе, это помогает предотвратить олицетворение путем кражи пароля (поскольку пароль не передается). Дополнительные сведения см. в этом вопросе на Security.SE.
Запрос сертификата клиента может быть выполнен только сервером. Если ваш сервер настроен на это, он отправит сообщение клиенту (вашему браузеру) во время рукопожатия SSL/TLS, и это сообщение обычно будет содержать список сертификатов ЦС, которым он доверяет, чтобы указать, какие клиентские сертификаты оно готово принять. (В этом конкретном случае ваш сервер, скорее всего, будет настроен на запрос клиентских сертификатов, выданных вашим ЦС.) Ваш сервер будет закодирован и настроен для этого (из вашего вопроса я не уверен, используете ли вы Контейнер Java Servlet или специальный Java-сервер).
Проверка сертификата выполняется диспетчером доверия в Java. Это часто инициализируется прозрачно, предоставляя приложению доверенное хранилище и полагаясь на поведение по умолчанию SSLContext
(затем используется по умолчанию SSLSocket
или SSLEngine
в зависимости от того, как закодировано ваше приложение). Предполагая, что ваш сервер использует диспетчер доверия по умолчанию и настроен на хранилище доверенных сертификатов, содержащее ваш сертификат ЦС (а также настроен на запрос сертификата), он отправит имя этого ЦС в браузеры, а не подключится к нему, и он будет также используйте этот ЦС для проверки сертификата, отправленного браузером. (Некоторые приложения также могут иметь настроенный диспетчер доверия, но тогда его поведение полностью зависит от того, для чего оно было написано.)
Java предоставляет два способа запроса сертификата: «нужен» или «хочу» (см. SSLSocket.setNeedClientAuth(...)
). Разница в том, что при «необходимости» соединение прекратится, если клиент не предъявил сертификат пользователя, тогда как в этом случае оно продолжится при «хочу».
После этого серверное приложение может проверить статус аутентификации пользователя, проверив одноранговый сертификат из файла SSLSession
. (Он не получит никакого однорангового сертификата, если клиент не отправил его, а сервер использовал режим «требования». Это может подойти для анонимного доступа.) На этом этапе (при условии, что серверное приложение было закодировано с правильным доверием менеджер, т.е. не фиктивный), код сервера будет гарантировать, что удаленный пользователь действительно является держателем закрытого ключа, соответствующего этому сертификату. Затем отличительное имя субъекта сертификата можно использовать в качестве идентификатора удаленной стороны. (Некоторые серверы позволяют при необходимости сопоставить это с другим набором имен пользователей. Это будет зависеть от того, какой именно сервер вы используете и как он настроен.)
Как вы сказали, цифровые сертификаты являются неотъемлемой частью ssl, не отличающейся от него (где цифровые сертификаты отправляются с сервера клиенту, содержащие открытый ключ и информацию о ЦС, которому доверяет браузер). Теперь браузер будет отправлять данные, зашифрованные с помощью открытого ключа, которые будут расшифрованы на стороне сервера с помощью закрытого ключа. Точно так же, когда сервер отправляет ответ, он будет обратным, то есть зашифрованным с помощью открытого ключа и расшифрованным с помощью открытого ключа на стороне браузера. Верно?
Нет, независимо от того, используете ли вы клиентские сертификаты или нет, соединение в любом случае будет зашифровано в обоих направлениях с использованием симметричного ключа, согласованного во время рукопожатия. Сертификат клиента тут ни при чем. Сертификат клиента используется только для подписи рукопожатия в конце, чтобы доказать серверу, что у клиента есть закрытый ключ для этого сертификата.
Детали в вашем редактировании, похоже, указывают на то, что вы используете конфигурацию, которая, вероятно, немного сложнее, чем обычно.
Во-первых, ваш Connector
не имеет атрибута clientAuth
(поэтому его значение по умолчанию равно false). Это означает, что сертификат клиента не будет получен во время первоначального рукопожатия, а будет инициирован вторым рукопожатием, когда вы попытаетесь получить доступ к защищенному ресурсу (в соответствии с вашей security-constraint
конфигурацией). Это называется повторными переговорами, и в этом нет ничего необычного.
(Я также заметил, что у него нет настроек, связанных с хранилищем доверенных сертификатов, что означает, что он использует хранилище доверенных сертификатов JRE по умолчанию, что также подразумевает, что ваш собственный сертификат ЦС должен быть явно импортирован в это хранилище доверенных сертификатов (в общем случае cacerts
). Сохраните это. иметь в виду, если вы обновите свою JRE, так как вам, вероятно, придется снова импортировать этот сертификат вручную.)
Ваша конфигурация tomcat-users.xml
— это то, о чем я говорил ранее (о сопоставлении DN субъектов с именами пользователей или ролями). Это, в сочетании с вашим нестандартным клапаном, является тем, что необычно в ваших настройках.
Я предполагаю, что этот клапан сопоставляет любой действительный сертификат с псевдо-пользователем с именем ignoreAndCheckInWebApp
, просто чтобы иметь возможность пройти это ограничение безопасности, хотя ожидается, что ваше приложение просматривает сам сертификат.
В более традиционном случае имена пользователей в tomcat-users.xml
будут DN субъектов ваших сертификатов, и таким образом вы сопоставите их с ролями. Здесь кажется, что ваше развертывание не заботится об этом сопоставлении в этот момент, но оно предназначено для проверки этого в вашем приложении позже. Вероятно, это означает, что ваше приложение должно напрямую полагаться на HttpServletRequest.getRemoteUser()
(если только оно не будет настроено фильтром позже), но должно считывать сертификат, используя атрибут "javax.servlet.request.X509Certificate"
из запроса.
Это может иметь смысл, если приложение делает все это правильно. То, что я здесь говорю, на самом деле является предположением, поскольку оно полностью зависит от того, как реализован клапан Tomcat. Это, безусловно, повлияет на имя удаленного пользователя и принципалы пользователей, которые вы получите.
Что касается ваших комментариев об ActiveX и IE, аутентификация с помощью клиентского сертификата также должна нормально работать с Firefox или Chrome. На ум приходят две вещи:
- Этот код ActiveX может просто не иметь ничего общего с клиентскими сертификатами, но может быть частью того, для чего предназначено приложение.
- Этот код ActiveX является частью вашего собственного ЦС и позволяет вашим пользователям подавать заявки на сертификаты из своих браузеров (если у них их еще нет). Возможно, это было реализовано только для IE, хотя это можно сделать и для Firefox или других браузеров.
person
Bruno
schedule
03.05.2014