OpenSSL представляет сертификат сервера клиенту с центром сертификации?
Я пытаюсь узнать, как использовать библиотеку OpenSSL (всего новичка), и у меня возникли проблемы с выяснением того, как подключить клиента к серверу с правильным сертификатом, и с ошибкой, если сертификат является неправильным. Мой пример использования - создание приложения p2p без центрального ЦС, поэтому я не могу полагаться на сертификат ЦС. В частности, сервер имеет сертификат / ключ как обычно, и клиент будет определять сертификат сервера, запрашивая другие узлы p2p для голосования.
У меня есть два конкретных вопроса:
- В приведенных ниже фрагментах кода я ожидаю, что клиент не подключится, если я закомментирую выбор под "списком шифров". Это все еще работает! Я что-то упустил, верно?
- Есть ли способ, чтобы клиент использовал сертификат сервера, и этого достаточно для открытия соединения? Т.е. нет ключа, нет CA?
клиент:
ctx = SSL_CTX_new(DTLSv1_client_method());
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH");
// If I comment out below stuff, client still connects happily!?
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
сервер:
SSL_CTX_set_cipher_list(ctx, "HIGH:!DSS:!aNULL@STRENGTH"); // high strength ciphers
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
if (!SSL_CTX_check_private_key (ctx))
printf("\nERROR: invalid private key!");
Мой код находится по адресу https://github.com/a34729t/exp/tree/master/tun2udp/dtls; он построен из примеров DTLS Робина Сеггельмана. В частности, я работаю с server3_oo.c.
1 ответ
SSL/TLS могут работать в разных режимах. Наиболее распространенным режимом является только аутентификация сервера, при которой только сервер имеет сертификат и ключ. Затем существует режим взаимной аутентификации, также называемый аутентификацией клиента, в котором клиент также имеет (клиентский) сертификат и ключ. Кроме того, существует полностью анонимный режим, в котором ни сервер, ни клиент не аутентифицируются, и ни сертификату, ни ключу не нужны.
Если вы не укажете OpenSSL иначе, он будет работать только в режиме аутентификации сервера. В этом режиме эти строки здесь, в клиенте:
if (!SSL_CTX_use_certificate_file(ctx, "certs/server-cert.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no certificate found!");
if (!SSL_CTX_use_PrivateKey_file(ctx, "certs/server-key.pem", SSL_FILETYPE_PEM))
printf("\nERROR: no private key found!");
приведет к тому, что клиент загрузит клиентский сертификат (кстати, вам никогда не придется загружать серверный сертификат и ключ в клиенте). Однако, поскольку сервер не запрашивает у клиента сертификат, клиент никогда не представляет его. Комментирование этих строк приводит к тому, что клиент не загружает какие-либо клиентские сертификаты, что не имеет значения, поскольку они все равно не используются.
Чтобы сервер запросил у клиента сертификат и чтобы сервер отказал в подключении, если он не представлен, вы должны указать серверу следующее (обработка ошибок опущена):
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_VERIFY_PEER
заставляет сервер запрашивать сертификат клиента и SSL_VERIFY_FAIL_IF_NO_PEER_CERT
заставляет сервер прервать соединение, если клиент не предоставляет сертификат (см. документацию). Если вы не используете последний вариант, вы можете проверить, отправил ли клиент сертификат с помощью функции SSL_get_peer_certificate.