
Доброго времени суток, %username%!
Ранее я рассказывал о генерации сертификатов с эллиптическими кривыми.
Сегодня я расскажу о том как можно без особых усилий настроить в IIS авторизацию по обычным RSAшным клиентским сертификатам, сгенерировать сертификаты для сервера и клиента. И поможет мне в этом как всегда OpenSSL.
Для того чтобы все работало нам понадобятся минимум 3 сертификата:
- Корневой сертификат (Certificate Authority или CA). Им будем подписывать все остальные.
- Сертификат домена (сервера). Им IIS будет проверять клиентов. И наоборот, клиенты смогут проверить подлинность сервера.
- Сертификат(ы) клиента(ов)

Для работы нам понадобится отдельная папка, например c:\iis. В ней необходимо создать файл без расширения serial и записать туда 01, так же там нужно создать пустой файл index.txt. В зависимости от конфигурации OpenSSL может попросить создать внутри этой папки еще какие нибудь. В моем случае это была папка newcerts. Так же в OpenSSL.cfg нужно будет поменять в [ CA_default ] dir на c:/iis
1) Создадим корневой self-signed сертификат:
openssl req -new -x509 -newkey rsa:2048 -days 1000 -out c:\iis\ca.crt -keyout c:\iis\ca.key
- -new означает что мы хотим создать новый запрос
- -x509 что сразу хотим самоподписанный сертификат
- -newkey rsa:2048 Пусть тут же и ключик нам сгенерирует длиной 2048 бит. вместо rsa:<кол-во бит>, кстати, можно указывать dsa:<файл с параметрами> или ec:<файл с параметрами>
- -days 1000 — сертификат истечет через 1000 дней
- -out и -keyout указывают куда сохранить сертификат и закрытый ключ от него
После серии несложных вопросов в папке iis появятся сертификат ca.crt и закрытый ключ от него ca.key
Теперь, чтобы IIS узнавал все сертификаты, подписанные корневым, нужно установить корневой сертификат в хранилище доверенных центров сертификатов компьютера:
- Запускаем mmc
- Добавляем оснастку сертификаты и указываем, что она будет управлять сертификатами для учетной записи компьютера, иначе ничего не заведется.
- Открываем «Доверенные корневые центры сертификации» и импортируем туда наш CA:

Готово! Можно приступать к работе с сервером.
2) В консоли управления IIS нужно зайти в «Сертификаты сервера», вызвать меню по правой кнопке и нажать создать новый запрос сертификата. Сохраните его в c:\iis как server.csr
Теперь подпишем запрос сертификата сервера корневым сертификатом:
openssl ca -days 1000 -policy policy_anything -keyfile c:\iis\ca.key -cert c:\iis\ca.crt -in c:\iis\server.csr -out c:\iis\server.cer
-policy policy_anything означает, что сертификату будут предоставлены все возможные политики применения. Самый простой вариант. Остальные параметры, полагаю, в пояснении не нуждаются. Главное, не запутаться где какой файл указывать.
После этого у нас в c:\iis появится сертификат сервера server.cer, которы нужно установить в IIS.
Для этого мы опять идем в «сертификаты сервера», выбираем «Запрос установки сертификата» и там указываем c:\iis\server.cer.
Всё, сертификат у сервера есть.
Теперь нужно в привязках для узла создать новую https привязку и выбрать из списка наш серверный сертификат:

После этого нужно в настройках SSL для узла выставить опции следующим образом:

Готово! Остался клиент. Но и на этом этапе уже можно зайти на https://localhost/ и увидеть, что без сертификата вас не пускает.
3) Генерируем запрос для клиентского сертификата
openssl req -new -newkey rsa:2048 -days 1000 -keyout c:\iis\client.key -out c:\iis\client.csr
Здесь мы не указывали -x509, поэтому получили обычный запрос на сертификат и закрытый ключ клиента.
Подписываем запрос:
openssl ca -days 1000 -policy policy_anything -keyfile c:\iis\ca.key -cert c:\iis\ca.crt -in c:\iis\client.csr -out c:\iis\client.crt
Тут тоже все понятно, в результате мы получим сертификат слиента client.crt
Теперь чтобы импортировать сертификат клиента в хранилище сертификатов Windows вместе с ключом, нам необходимо конвертнуть crt+key в контейнер .pfx:
openssl pkcs12 -export -inkey c:\iis\client.key -in c:\iis\client.crt -out c:\iis\client.pfx
Ура! Получили client.pfx, дважды кликнув на котором можно вызвать диалог импорта сертификатов и, собственно установить то что получилось в личное хранилище.
Если все сделано правильно, то после импорта сертификата в личное хранилище вас должно пустить по адресу https://localhost/ и показать содержимое.
Можно сгенерировать еще один сертификат с другими данными и тоже его импортировать. Тогда при заходе на сервер вам предложат выбрать любой из них:

Вот и все )
На последок код aspx странички (сохраните его как Default.aspx), который позволит вам всё проверить: Он выводит информацию о клиентском сертификате:
<%@ Page Language="C#"%>
<%@ Import Namespace="System.Security.Cryptography" %>
<script runat="server">
private void Page_Load(object sender, System.EventArgs e)
{
Response.Write("<table width=50% cellspacing=1><tr> <th colspan=2>Current ClientCertificate Settings</th></tr>");
Response.Write("<tr><td>Subject</td><td>"+Request.ClientCertificate.Subject+"</td></tr>");
Response.Write("<tr><td>SHA1 Fingerprint</td><td>"+GetCertificateFingerPrint()+"</td></tr>");
Response.Write("<tr><td>Valid from</td><td>"+Request.ClientCertificate.ValidFrom+"</td></tr>");
Response.Write("<tr><td>Valid Until</td><td>"+Request.ClientCertificate.ValidUntil+"</td></tr>");
Response.Write("<tr><td>Issuer</td><td>"+Request.ClientCertificate.Issuer+"</td></tr></table>");
}
private String GetCertificateFingerPrint()
{
if (Request.ClientCertificate.IsPresent)
{
byte[] raw = Request.ClientCertificate.Certificate;
SHA1 sha1 = new SHA1CryptoServiceProvider();
byte[] hash = sha1.ComputeHash(raw);
StringBuilder res = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
res.Append(hash[i].ToString("X2"));
}
return res.ToString();
}
return "";
}
</script>