# $Id: ssl_certificates.howto.txt,v 1.4 2007/04/23 08:32:39 aost Exp $ Как готовить ssl сертификаты для авторизации клиента на http сервере. В интернете найдется много статей, в которых описано - как создавать ssl сертификаты, но общее назначение тех сертификатов: серверные, для создания шифрованного ssl соединения между сервером и клиентом. Примерно те же самые сертификаты могут играть еще и роль ключа для авторизации клиента на сервере. Обычно для этого достаточно, чтобы на сервере лежал сертификат CA (certificate autority), а у клиента были ключ и сертификат, выпущенные (подписанные) этим самым CA. Теоретически, для такой авторизации клиента, можно использовать распространенные self-signed сертификаты, но тогда несколько искажается сам смысл авторизации клиентов, т.к., для каждого клиента нужно будет добавлять свой (а, по сути, его) CA на сервер - в результате никакой секьюрити. В данной статье рассматривается создание клиентских сертификатов с помощью отдельного CA. В случае использования сервера Apache (http.apache.org) конфиги кроме традиционного включения ssl SSLEngine on SSLCertificateFile apache2/ssl.crt/server.crt SSLCertificateKeyFile apache2/ssl.key/server.key должны содержать упоминание о клиенте: SSLVerifyClient require SSLVerifyDepth 10 SSLCACertificatePath apache2/client/ $ ls apache2/client2/ 929d833a.0 --> client-ca.crt Makefile client-ca.crt Makefile взят откуда-то из стандартной поставки апача. ## Makefile to keep the hash symlinks in SSLCACertificatePath up to date ## Copyright (c) 1998-2001 Ralf S. Engelschall, All Rights Reserved. В случае использования сервера nginx (www.sysoev.ru) конфиги выглядят примерно так: server { .... ssl_client_certificate ssl_client/client-ca.pem; ssl_verify_client on; ssl_verify_depth 1; .... } Формат файла, содержащего открытую часть (сертификат) CA client-ca.* в обоих случаях один и тот же: pem -----BEGIN CERTIFICATE----- MIIEhDCCA2ygAwIBAgIJAJipCj8ATGonMA0GCSqGSIb3DQEBBAUAMIG9MQswCQYD VQQGEwJSVTEaMBgGA1UECBMRTm9ydGgtV2VzdCBSdXNzaWExFjAUBgNVBAcTDVN0 Итак, приступим к созданию сертификатов. Создаем рабочую директорию ${HOME}/ssl_certificates со структурой описанной в механизме создания сертификатов для первого апача (с demoCA внутри). Одно из отличий - в ней лежит кусочек модифицированного openssl.cnf - client.cnf для генерации клиенских запросов. [ v3_req ] # client basicConstraints = CA:FALSE nsCertType = server, client, email, objsign keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment # constatnt subjectAltName = email:copy nsComment = "OpenSSL Generated Certificate" > Может имеет значение то, что cacert.pem self-signed? Нет. Тот ключ/сертификат, которыми мы подписываем сертификат клиента должен иметь всякие флаги, типа: X509v3 Basic Constraints: CA:TRUE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Certificate Sign, CRL Sign Или в теримнах openssl конфиг-файла: [ v3_req ] subjectAltName = email:copy basicConstraints = CA:true keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign nsComment = "CA certificate of Organisation" nsCertType = sslCA Хотя, у меня и безо всех этих ухищрений иногда работало. Это для токена, как выяснилось, обязательно нужны такие рюшечки. Создание CA (S) и клиентского (C) сертификатов проходит примерно одни и те же шаги: 1. создание файла private ключа со своим паролем, 2. создание файла-запроса (CSR) на подпись, 3. подписание запроса. 4. конвертация данных из формата PEM в формат PKCS12 для экспорта клиентам. ============================= 1. Генерируем CA private key размером 2048 байт. "Generate RSA private key" S/C> openssl genrsa -des -out server_private.key 2048 ============================= 2. Создаем файл запроса сертификата. Server> openssl req -new -key server_private.key -config /etc/ssl/org.cnf \ -out CA_request.csr Client> openssl req -new -key client_test.key -config client.cnf \ -out client_certificate_request.csr ============================= Смотрим на то, что получилось в результате: S/C> openssl req -text -noout -in CA_request.csr Нас интересует вот эта секция: Requested Extensions: X509v3 Basic Constraints: CA:TRUE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Certificate Sign, CRL Sign Netscape Cert Type: SSL CA У клиента должно быть: X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment ============================= 3. Создаем (само)подписанный сертификат: Server> openssl x509 -req -signkey server_private.key -in CA_request.csr \ -extfile /etc/ssl/org.cnf -out CA_main.crt \ -extensions v3_req -days 365 Client> openssl ca -policy policy_anything -out client_work_certificate.crt \ -extfile client.cnf -extensions v3_req \ -infiles client_certificate_request.csr 4. Для экспорта в pkcs12 формат делаем: http://www.openssl.org/docs/apps/pkcs12.html S/C> openssl pkcs12 -export -chain -CAfile demoCA/cacert.pem -in client_work_certificate.crt \ -inkey client_test.key -out iestuff.p12 Enter pass phrase for client_test.key: Enter Export Password: Verifying - Enter Export Password: Полученный бинарный файл формата pkcs12 может быть импортирован непосредственно в web-браузер типа IE или Firefox, либо в токен. Генерация CRL листа S> openssl ca -gencrl -verbose > client_revocation.crl Просмотр S> openssl crl -noout -text -in client_revocation.crl Для отзыва сертификата, используя штатный механизм CRL, необходимо файлы сертификатов клиентов где-то складировать с привязкой по клиенту. > openssl ca -revoke bad_certificate.pem Using configuration from /etc/ssl/openssl.cnf Enter pass phrase for ./demoCA/private/cakey.pem: DEBUG[load_index]: unique_subject = "no" Revoking Certificate 123492. Data Base Updated Для отзыва нештатными методами - редактируем напрямую файл index.txt msg> -V 070802141533Z 123494 unknown /C=RU/ST=.... msg> +R 070802141533Z 060804122324Z 123494 unknown /C=RU/ST=.... Ну, а дальше, как и после -revoke надо перегенерировать CRL лист командой -gencrl