Мне нужен фрагмент кода для программы, с которой я пишу Boost Asio SSL
,
У меня есть система из двух клиентов, которые связаны друг с другом. Я требую от них взаимной аутентификации, чтобы в конце handshake()
Команда, оба клиента могут быть уверены, что другой клиент имеет закрытый ключ к сертификату, который они предоставили.
Оба клиента имеют context
объект, давайте называть их ctx1
а также ctx2
и у каждого клиента есть открытый сертификат и закрытый ключ.
Можно ли настроить объекты контекста так, чтобы при вызове socket.handshake()
клиенты будут выполнять двустороннюю аутентификацию. Если нет, каков будет правильный путь для достижения моей цели?
Похоже, Boost просто использует интерфейс OpenSSL.
Я не знаю, что такое boost, но я реализовал множество внутренних компонентов OpenSSL для Perl и пришел к следующим выводам после прочтения соответствующих частей исходного кода boost:
Для взаимной аутентификации с OpenSSL вы должны использовать SSL_VERIFY_PEER
на стороне клиента и SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
на стороне сервера. Если вы используете только SSL_VERIFY_PEER
на стороне сервера он только отправит запрос сертификата клиенту, но молча примет, если клиент не отправляет сертификат обратно.
С надстройкой это, вероятно, будет:
ctx.set_verify_mode(ssl::verify_peer); // client side
ctx.set_verify_mode(ssl::verify_peer|ssl::verify_fail_if_no_peer_cert); // server side
Если вы установите флажок verify_mode таким образом, он будет проверять сертификаты по настроенным доверенным CA (установлен с ctx.load_verify_file
или же ctx.load_verify_path
).
Если у вас есть полный контроль над центром сертификации, подписавшим сертификаты (т. Е. Вашим собственным центром сертификации), вам может быть достаточно принять любые сертификаты, подписанные этим центром сертификации. Но если вы используете ЦС, который также подписал сертификаты, которые вы не хотите принимать, как обычно в случае с общедоступными ЦС, вам также необходимо проверить содержимое сертификата. Подробности того, как это сделать, зависят от вашего протокола, но для обычных интернет-протоколов, таких как HTTP или SMTP, это включает проверку commonName и / или subjectAltNames сертификата. Детали, такие как обработка подстановочных знаков, различаются в разных протоколах
Повышение обеспечивает rfc2818_verification чтобы помочь вам с проверкой в стиле HTTP, хотя при чтении кода я думаю, что реализация немного ошибочна (допускается несколько подстановочных знаков, допускаются подстановочные знаки IDN — требования см. в RFC6125).
Я не знаю каких-либо стандартов для проверки клиентских сертификатов. Часто принимаются только любые сертификаты, подписанные определенным (частным) ЦС. В других случаях сертификаты из общедоступного ЦС соответствуют определенному шаблону электронной почты. Похоже, в этом случае boost не сильно вам поможет, поэтому вам, вероятно, придется получить OpenSSL. SSL*
справляться sock.native_handle()
а затем использовать функции OpenSSL для извлечения сертификата (SSL_get_peer_certificate
) и проверить содержимое сертификата (различные X509_*
функции).
По крайней мере, если задействованы публичные центры сертификации, вы также должны проверить статус отзыва сертификатов. Похоже, Boost не предоставляет прямой интерфейс с CRL (список отзыва сертификатов), поэтому вы должны использовать ctx.native_handle()
с соответствующими функциями OpenSSL (X509_STORE_add_crl
так далее). Использование OCSP (онлайн-протокола отзыва статуса) является более сложным, и соответствующие функции OpenSSL в основном не документированы, что означает, что вы должны прочитать исходный код OpenSSL, чтобы использовать их 🙁
Нельзя заставить другую сторону аутентифицироваться против вас, это зависит от протокола, каждая сторона аутентифицируется только против другой стороны. Просто следуйте инструкциям, как http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/ssl.html
ssl::context ctx(ssl::context::sslv23);
ctx.set_verify_mode(ssl::verify_peer);
ctx.load_verify_file("ca.pem");