Pull to refresh

Comments 52

А вот эта статья никак не поможет сэкономить 2000 на извлечении ключа?
https://habrahabr.ru/post/276057/
Вполне возможно. Отличный совет! Когда/если найду время, чтобы своими руками проверить статью — обновлю пост.
Разве Крипто-про не позволяет скопировать контейнер закрытого ключа?
есть в тексте. Ctrl+F в браузере, «Как мы можем попросить Крипто Про отдать ключи (на самом деле, нет)»
Вы что-то делаете не так. Приведенная ссылка на форум — 6 летней давности. Сейчас ключи прекрасно экспортируются в PFX и импортируются обратно. Я сам очень давно (лет 5-6 назад) сталкивался с проблемой невозможности экспорта в PFX, однако, относительно недавно обнаружил, что это работает — изучая пример, идущий с КриптоПро.NET SDK (как раз про SMEV), обнаружил там в каталоге Certificates примеры ключей в PFX и в readme.txt написано что эти PFX устанавливаются штатными средствами системы. Проверил на своих сертификатах — действительно, всё работает.
Тем не менее, закрытый ключ не экспортируется сейчас, в 2016 году. Это факт.

Импорта не проверял — цель ведь сбежать с крипты, а не прибежать в неё.
Закрытый ключ прекрасно экспортируется. Это факт. Экспортировал в 2016 году. Специализированного софта для этого не устанавливал — только КриптоПро 3.9 КС1
Ну то есть иногда экспортируется, иногда — нет. Какой-то баг, наверное. Как всегда :)

Если уж на то пошло, то на Linux через админку КриптоПро JCP нету вообще никаких опций экспорта кроме одной — «Экспорт» без описания. Оно экспортит в неназванный формат без расширения имени файла, который содержит в себе только открытый ключ. А на OSX даже эта админка либо не запускается, либо сыпет багами. А если захочешь установить ключи, устанавливать их надо копированием в магическую директорию, путь который ищется на форуме, и из интефрейса админки JCP это не делается. Думаю, если тут «кто-то делает не так», искать надо начинать не с меня, а например, с самой Крипты.
Как мы можем грубо заставить Крипто Про отдать ключи

Требовать, чтобы ключи по-честному генерировались на токенах PKCS#11 с ГОСТ-ами, а не использовали токен как флешкуЙ!!.. Тогда не будет проблем ни с чем. А уж OpenSSL умеет работать с токенами PKCS#11.

Простите за «глупость» но для экспорта всех ключей из системы разве нельзя использовать известный mimikatz? он еще и с открытыми исходниками.
Мне он (mimikatz) неизвестен. Спасибо за подсказку.

Не все так просто. jailbreak 4.0/3.5 не экспортируют неэкспортируемый ГОСТ Р 34.11/34.10-2001-ГОСТ Р 34.11-94 ключ, ни через jbcert


Не удалось выполнить экспорт.
Ключ не может быть использован в указанном состоянии.

ни через jbstore -a


Error sizing blob: -2146893813
This is because jbstore2 is not working, Are you using jailbreak32/64 to launch
it?
If there are still problems please contact iSEC Partners.

mimikatz 2.1.1-20170409 же не может экспортировать ключ, так как crypto::capi и crypto::cng не поддерживают нужные криптопровайдеры.
Обе программы сертификат видят.

Тем не менее, если ключ хранится в реестре, то он может быть извлечен из веток HKLM\SOFTWARE\CryptoPro\Settings\Users\{SID}\Keys\ или HKLM\SOFTWARE\Wow6432Node\CryptoPro\Settings\Users\{SID}\Keys\, а затем, например, сконвертирован утилитой privkey для использования в OpenSSL (прежде нужно удалить пароль с криптоконтейнера через CSP > Сервис > Изменить пароль... > Выбрать контейнер > Не вводить пароль).

Да, избавиться от Крипто-Про и сотоварищей довольно насущная задача. Сейчас как раз с коллегой решаем задачу взаимодействия с http://dom.gosuslugi.ru, которые не навязчиво рекомендуют единственное решение.
Половина уже решена средствами openssl + обёртка на питоне и есть надежда на полный успех. Сильно не хватает нормальных интерфейсов работы с openssl на питоне, с поддержкой дополнительных движков криптопровайдеров. Тот же pyopenssl не умеет пока. Но, надеюсь, в будущем ситуация улучшится, благо все возможности есть.
Избавиться от Крипто-Про в тестовых целях конечно можно, но на проде у вас могут следующие грабли:
1. Поддержка ключевых носителей eToken, Соболь, и т.д.
2. Поддержка параметров алгоритмов.
3. Работа с аппаратными генераторами случайных чисел.
4. Экзотические грабли, но тем не менее — переход на новые шифры «Кузнечик», «Стрибог» и т.д. не факт что в Bounty Castle оперативна появится их поддержка.

Хотя если делать замену КП на BC как черного ящика, то есть нечто что шифрует, то такой способ имеет место быть.
Не в качестве рекламы, а в качестве учебника по работе с надфилем XML-Security Java and MS CryptoIAPI for CXF WS-Security signature. Меня умиляют эти слова о Apache Santuario и код работы с DOM деревом. Apache Santuario — это для XML SAX разбора. Для DOM дерева используется JSR105.
Да, проект опубликован давно, но отнюдь не означает, что он не работает. Там идут JUnit тесты и работаю. Заметьте, работают под Linux и под Windows.

Зачем сражаться с контейнерами закрытых ключей? Покупка КриптоПро CSP по цене соизмерима со стоимостью некой утилиты. И не факт, что она сможет извлечь ключи с аналогов eToken.
Посмотрите на недавно сертифицированную CSP 4.0. Там есть куча компонентов с полюбившимся OpenSSL.
кстати, код работы с DOM-деревом по сути не мой — это расширение того, что уже написано в официальном СМЭВ-клиенте. Описанная в статье копипаста — малоинтрузивный патч. Меньше строчек поменяешь — проще будет поддерживать, патчить обновления клиента. В джавадоке по методу, о котром идет речь, есть комментарий на тему, что автор кода не разобрался, почему весь этот текст нужно писать, но без него не работает, поэтому он просто оставит это здесь :)
Я предлагаю всё же разобраться в том, что написано другим человеком.

На самом деле, я хочу вам показать пример реализации с Apache CXF. Здесь нет надобности вообще каким-то образом обрабатывать XML документ. JAXB и JaxWS делают много вещей для вас. Вы используете обычные классы. Далее, поднимаем SOAP клиента на основе WSDL и вкладываем в качестве параметра нужный Java класс.
Вся работа с криптографией, прописывание подписей в XML, извлечение и проверка подписей, это удел Apache CXF. Ваш код должен быть «мягким и пушистым», а не вызывать сложные рефлексы.

Самое основное понимание XML подписи — не надо стремится сохранить текстовое представление документа. В подписи указывается алгоритм нормализации. Он убирает все отступы и упорядочивает названия атрибутов в тегах. Полученная каша, в кодировке UTF-8 поступает в хеш функцию. Значение функции находится в разделе digest. Подпись собирает все эти дайджесты вместе и уже подписывает.

Я извиняюсь, если не совсем доходчиво объясняю.
Вы доходчиво объяснете, самые ценные комменты в теме
Покупка КриптоПро CSP по цене соизмерима со стоимостью

«Лицензия на право использования СКЗИ „
КриптоПро JCP“ версии 2.0 на одном
сервере с одним ядром процессора (или с 2 ядрами с отключенным Hyper
Threading)»

https://www.cryptopro.ru/sites/default/files/docs/price.pdf

То есть, если я, в тестовых целях, энсиблом пачкой зафигачу свою софтину в сотню-другую докеров, на покупку лицензий мне придется продать на черном рынке машину, кваритру, собаку, жену, и все свои внутренние органы?

> соизмерима со стоимостью некой утилиты

если когда-нибудь у меня случится отпуск, таки напишу эту утилиту прямо на гитхаб, и это будет стоить вообще ничего никому
Вы пишете клиента или вы пишете сервер?
Обратите внимание на этот вопрос. Клиенты могут воспринимать вашу систему как сервер. Но ваша система может являться промежуточным звеном на этапе передачи данных во внешнюю систему. Другими словами, вы выступаете инициатором передачи сообщения — вы клиент. Это главное понимание.
Если же ваша система является получателем, вы выступаете в качестве сервера — стоите и слушаете, когда кто-то к вам подключится.
Точно так же в установке TLS соединения. Ваш browser выступает в роли клиента и ему не нужна серверная лицензия на КриптоПро CSP.
То же самое происходит и с лицензированием КриптоПро JCP/JCSP и JTLS. Для Клиентского ПО, JTLS бесплатно — так утверждают сами сотрудники КриптоПро. JCP так же идет по лицензии клиента.
Смэв — это шина. По шине бегают сообщения. Сервисы обрабатывают входящие сообщения и на основании этого забрасывают в шину собственные сообщения. Сообщения — это XMLки, подписанные по госту. Так что сервисы — это автономные полностью автоматические серверы, никаких браузеров и прочих веб-интерфейсов там нет.
Вы считаете, что ваше ПО выступает в качестве автономных сервисов. Поймите, что слово сервис — это клиент шины. Сервер — это средство хранения и обмена в вашей шине. По аналогии, это SMTP/POP сервера электронной почты. У вас всего лишь почтовый клиент.
То же самое в MQ или JMS. Есть один или несколько серверов, на которые поступают сообщения и они передают их клиентам. Клиент может публиковать сообщения, может забирать корреспонденцию. Но при этом, он остается для шины клиентом.
С точки зрения, вы делаете клиента. Сервер у вас пассивный.

В рамках Java программ, мы создаем сокеты. Для понимания, о чем я говорю, можно посмотреть статью Создаем клиент-сервер на сокетах.
Если вы создаете ServerSocket, это сервер. Если создаете Socket, это клиент.

Теперь представим такую ситуацию. У нас есть SOAP сообщение от клиента. Он подписывает сообщение и отправляет на сервер. Сервер отправляет ответ. Если ответ сервера должен быть подписан, ему нужна серверная лицензия.

Еще раз повторю, что сервис в шине — это клиент.
Он спрашивает у сервера наличие сообщений и получает сообщения в ответ. То что ваш сервис, это клиент, понятно?
После получения ответа, ваше ПО отключается от сервера и может не спеша подготовить ответ на полученное сообщение. После этого, ваш сервис подключается к серверу обмена и передает туда свое сообщение для отправителя исходного сообщения. Получает ответ от сервера, что он получил сообщение. То что ваш сервис — это клиент, понятно?
В чем же главное отличие сервера от клиента? Сервер не может самостоятельно установить соединение с клиентом. А вот, клиент может установить соединение с сервером.

Вам хватит клиентской лицензии на средства криптографии.
Ответы тоже должны быть подписаны
Про CSP вы совершенно правы. Про КП JCP — не уверен. Я Java не использую, но КП.NET совершенно точно лицензируется по используемой операционной системе и не важно, что использование КП.NET ограничивается клиентскими нуждами. Благо, для КП.NET лицензирование не по ядрам :).
Коллеги, разрешите вступлюсь за КриптоПРО.
Клиентская лицензия для КП CSP (без возможности формирования ЭП + только клиентский TLS) — бесплатна.
Кому надо можете запросить соответствующее письмо у них в офисе.
Если ваши сервисы только проверяют электронную подпись то да.
Скажу крамольную истину. Если вам надо только проверять подписи и не заниматься подписыванием сообщений, вы можете использовать КриптоПро JCP и не платить. Да, это не честно, но работает.
Сервисы в основном подписывают исходящие. Входящие можно проверить, но необязательно.
>> Некая контора под названием Лисси Софт
>> Со слезами — потому что это проприетарщина, и она фиг знает как работает.

Эти «Лисси» умудрились даже исходники Firefox и Thunderbird спиратить. Оправдываются тем, что «У микрософта исходники тоже закрыты».
А зачем им тырить Firefox и Thunderbird? В чем профит? Вот же они, в инторнете лежат.
Под «стырили» я подразумевал то, что они взяли исходники, сделали на их основе версии с поддержкой российского крипто, но эти производные продукты внезапно стали проприетарные. Хотя, по лицензии, под которой они брали сорцы (Firefox и Thunderbird распространяются на условиях GNU GPL) — Лисси обязаны предоставлять исходный код своих изменений по первому же запросу пользователей.
Понятия не имею, мне, к счастью, не так нужны эти бинарные блобы, чтобы за них судиться.
Что, впрочем, не отменяет того факта, что «Лисси» поступает, мягко говоря, нехорошо. С linux.org.ru их за это уже шуганули после попыток пиарить там свои поделия.
Вдобавок, возникает интересный каламбур — они предлагают довериться российской криптографии, но для этого, зачем-то, надо доверится сначала самой «Лисси».
Да, я и репортил модераторам лора просьбу удалить их пиар, вспомнил теперь :)
Но вы подали мне идею с судом — сообщил в Mozilla о нарушении лицензии. У них на сайте есть для этого форма. В конце-концов, это их права нарушены, им и судиться, если оно им надо.

И после этого еще кто-то смеет жаловаться на проблемы безопасности! Да если для того, чтобы вся эта криптография хоть как-то заработала, нужно гуглить днями и вставлять спагетти непонятно как и почему работающего кода — неудивительно, что статьи об уязвимостях просто прут пачками.


Асимметричная криптография в основе своей проста, как два пальца, почему же ее использование сопряжено с такими трудностями? Где внятные мануалы? Примеры кода? Вот, например, у меня как раз стоит задача прочитать приходящий PKCS#7 сертификат (в виде массива байт) и проверить подписи в нем, так даже для такой элементарной задачи (если не пользоваться классом PCKS7 из пакета sun.*) нужно наворотить такую кучу кода, что волосы дыбом встают. Причем у всех кода разный и у меня впечатление, что никто не знает, как же это делать правильно. Во всяком случае, понимания того, что происходит, я ни в одном из ответов на stackoverflow не вижу. О генерации ответа в таком же формате (отдать свой подписанный публичный ключ) я пока даже боюсь думать, настолько все запутанно и неочевидно.

PKCS#7 — это контейнер, используемый в криптографии. Сертификат, обычно, передается в контейнере PKCS#7, вместе с подписью.
В контейнер можно положить несколько сертификатов. И будет у нас хранилище сертификатов.
Можно положить CRL файлы. Можно положить подписываемое сообщение. Можно положить зашифрованное сообщение.
Отсюда и идут все сложности в понимании.

Да, в самом сертификате есть подпись издателя и сведения о сертификате издателя. Но сам сертификат не является контейнером формата PKCS#7.

Для чтения и записи сертификата и контейнера используется стандарт ASN1.
Отсюда и все сложности на этапе освоения всего этого нагромождения.
PKCS#7 это не контейнер для сертификата. Это запрос на сертификат, содержащий subject, публичный ключ и, возможно, дополнительные поля. Все это подписано приватным ключем, который никуда не передается.
СА получает запрос, извлекает публичный ключ и используя его проверяет подпись всего запроса. Если да — добавить поля Issuer, поменять/заменить/добавить дополнительный полей и подписать все это своим приватным ключом CA. Так получается сертификат.
Далее его можно отдать как есть (bin или base64), можно спрятать в контейнер PKCS#12 под пароль и отдать в нем.

О криках про шифрование и ключи. Основная задача криптографии не в алгоритмах. Основные трудности (основной упор всех разработок) — создание ключей (надежный непредсказуемый ДСЧ, от чего и появляются аппаратные прибамбасы) и надежный/стойкий метод хранения ключей (приватных в том числе).

О какой надежности системы можно говорить, если ПРИВАТНЫЕ ключи «ходят по рукам», перекладываются и «светятся» чуть ли не в открытом виде? Алгоритмы описаны на каждом втором вебсайте — приватность именно в хранении ключей. Любой СКЗИ работает по принципу «мы вам сделаем внутри ключ, вы можете использовать его для шифрования/подписи, но сам ключ (его содержимое) будет тайной за семью печатями и для вас тоже».

Посмотрите как устроены токены? Посмотрите как сделана ваша СИМ-карта в телефоне наконец — она свой ключ Ki не светит нигде и никогда.
Но использует вовсю.
Вы бы заглянули на сайт wiki статью PKCS. Запрос на сертификат — это PKCS#10. Разные устройства, типа eToken, это стандарт PKCS#11.

Что смотреть в этой карточке или USB token? Микроконтроллер. Разве, что, на специальном оборудовании снимать с него стружку. Эти устройства хороши, но очень медленные. Вот, вы, пишите ответ в данной статье. Обмен с сервером идет в зашифрованном протоколе TLS. Теперь, ваш поток мыслей должен пройти через эту карточку / USBToken. После этого, данные уйдут на сервер. Данных не много. А теперь представьте, что этот сервер так же, весь трафик, все HTML статьи, будет гонять через USB Token. Данная технология имеет право на жизнь в некоторых областях применения.
ОК, я был не совсем прав. Да, запрос это PKCS#10.
Проблема в том, что PKCS#7 && PKCS#12 не могут выступать в роли хранилищ сертификатов и ключей. Эти протоколы разрабатывались только как транспортные.
Для хранения — токены (и связанный с ними протокол обмена (!!) PKCS#11), или новый PKCS#15

Основной вопрос был в попытке оправдать идеологию СКЗИ хранить свою приватную информацию в закрытом ото всех виде. В том числе и от владельца ключа. Обращаться к СКЗИ для использования этого ключа можно, экспортировать и унести ключ — должно быть запрещено.

Токены я упомянул (равно как и SIM) — пример того, что ключ создан, но пользователь его не видит и не может получить. Он скрыт внутри микросхемы контроллера. Вы можете его использовать, выдавая запросы на операции с этим ключом, микроконтроллер будет отвечать.

И… давайте не будем меряться скоростями? Есть много решений, почему вы думаете что все токены работают на USB? Но я вовсе не склоняю всех использовать токены как СКЗИ, это скорее пример реализации закрытых ключей. Закрытых «совсем».
olegchir, какой класс СКЗИ применяется (должна применяться — КС1, КС2, КС3, КВ1, КВ2, КА1) в Вашей системе в соответствии с требованиями?
чем выше класс СКЗИ, тем больше требований к окружению (аппаратный ДСЧ, контроль загрузки и т.д.), не придется потом сильно менять платформу (ОС, версии ПО и др.) для соответствия классу?
странный вопрос… требования то для всех едины (210 приказ минкомсвязи от 23 июня 2015) А так — какой в модели угроз написан ;) А там написано, что криптография нам вообще не нужна ;))
вы правы, промахнулся

Спасибо за статью, в своё весёлое прошлое нырнул на ночь глядя. В 2014-м году использовал разные криптовайдеры. И сравнивал скорость работы КриптоПро 3.6 и Bouncy Castle .NET. КриптоПро 3.6 работал существенно быстрее. Задача — формирование отсоединённой подписи для файла в нагрузочных тестах. Другая задача — формирование ключевой пары и сертификата, для тестовых пользователей формировал 10 000 ключевых пар и сертификатов (или около того).


В результате поступил так. Ключевую пару формировал в КриптоПро, а вот сертификат со всеми нужными атрибутами и свойствами мастерил в Bouncy Castle, там полная свобода. И с помощью Bouncy Castle сделал малый УЦ — выпуск сертификатов, CRL-ответчик, OCSP-ответчик. При подписании документов, получается, снова работал КриптоПро, так как закрытый ключ в нём хранился, а Bouncy Castle трудился только чтобы CRL и OCSP отдавать для формирования усовершенствованной подписи. Никакой из действующих УЦ мне бы никогда не выдал 10 000 ключей бесплатно, и не стал бы мне OCSP-ответы с дикой скоростью отдавать. OCSP-ответчики действующих УЦ умирали от нагрузки реальных клиентов. Тут Bouncy Castle помог.


Была задумка сделать масштабное сравнение скорости работы. Так как в .NET очень удобный CryptoAPI, который для простых задач, таких как формирование и проверка подписи скрывает детали взаимодействия с криптопровайдером до 0-ля. Нужно немного смекалки и умения обходить баги, чтобы водрузить на одну машину несколько криптопровайдеров сразу, а потом можно их тестировать одним и тем же кодом, лишь используя сертификаты, ключи к которым хранятся в разных криптопровайдерах. При условии, что на ключах нет пароля и есть лишь одно хранилище, всё проходит быстро и просто, без лишних диалогов от КриптоПро или VipNet.


Скоро ожидаю, что на работе будет проект с криптографией, тогда осуществлю задуманное. Сравню, VipNet, Lissy CSP, Crypto Pro, BounsyCastle. Их можно параллельно использовать. А вот, например, белорусский ГОСТ-криптопровайдер Avest CSP использовать вместе с КриптоПро было нельзя в 2014-м году. Предполагаю, они используют один и тот же идентификатор криптопровайдера или алгоритмов, и тот что установился последним, считался криптовайдером, реализующим ГОСТ-алгоритмы первого — это частично недостаток CryptoAPI для .NET, где нельзя тонко настроить этот момент, CryptoAPI считывает из реестра кто и что реализует, и в случае, если два провайдера реализуют одно и то же, сам принимает решение, какой из них использовать.

Примечание по скорости тестовых CRL и OCSP. Ответчики, сделанные на базе Bouncy Castle, работали быстро под натиском нагрузочных тестов, во многом, потому, что всегда отвечали, что с тестовыми сертификатами всё хорошо — были заглушками. CRL генерировался нечасто и грамотно кешировался, но тут реализовал всё полностью, можно было сделать сертификат отозванным. А OCSP-ответ всегда был положительным для любых сертификатов — заглушка. Вот всё и летало, как пуля.

Я всегда был уверен, что CRL издает центр сертификации УЦ (он и сертификаты издает). Как же Вы умудрились подписывать CRL не КриптоПро-шным криптопровайдером? Как то этот момент у меня не вяжется.

Сертификат и цифровая подпись — данные в формате ASN.1, которые, как видно выше, можно мастерить, используя Bouncy Castle. CRL — тоже данные в формате ASN.1, которые как и сертификат подписаны ключом УЦ. Если Bouncy Castle может прочитать ключ, то Bouncy Castle может сформировать CRL.


Есть удобный класс: X509V2CrlGenerator.


Пример кода на C#
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;

...

X509Crl GetCrl()
{
    DateTime thisUpdate = DateTime.UtcNow;
    DateTime nextUpdate = thisUpdate.AddMinutes(Settings.CrlLifeTimeInMunutes);

    Org.BouncyCastle.Asn1.DerObjectIdentifier crlNextPublish = new Org.BouncyCastle.Asn1.DerObjectIdentifier("1.3.6.1.4.1.311.21.4");
    Org.BouncyCastle.Asn1.DerObjectIdentifier crlNumberOid = new Org.BouncyCastle.Asn1.DerObjectIdentifier("2.5.29.20");

    if (System.IO.File.Exists(Settings.CrlFilePath))
    {
        FileInfo crlFileInfo = new FileInfo(Settings.CrlFilePath);
        X509CrlParser crlParser = new X509CrlParser();
        X509Crl prevCrl = crlParser.ReadCrl(System.IO.File.ReadAllBytes(Settings.CrlFilePath));
        if (DateTime.UtcNow >= prevCrl.NextUpdate.Value)
        {

            X509V2CrlGenerator generator = new X509V2CrlGenerator();
            generator.AddCrl(prevCrl);
            generator.SetThisUpdate(thisUpdate);
            generator.SetNextUpdate(nextUpdate);
            generator.SetSignatureAlgorithm(Settings.SigningAlgorithm);
            generator.SetIssuerDN(Certificate.SubjectDN);
            generator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(Settings.CACertificate));
            //Установка даты следующего обновления (crlNextPublish)
            generator.AddExtension(crlNextPublish, false, new Org.BouncyCastle.Asn1.DerUtcTime(nextUpdate));
            //Получение текущего номера CRL (crlNumber)
            if (prevCrl.GetExtensionValue(crlNumberOid) != null)
            {
                Org.BouncyCastle.Asn1.DerInteger crlNumber = (Org.BouncyCastle.Asn1.DerInteger)Org.BouncyCastle.Asn1.DerInteger
                    .FromByteArray(prevCrl.GetExtensionValue(crlNumberOid).GetOctets());
                //Увеличение номера на 1
                crlNumber = new Org.BouncyCastle.Asn1.DerInteger(crlNumber.Value.IntValue + 1);
                //Установка нового номера CRL (crlNumber)
                generator.AddExtension(crlNumberOid, false, crlNumber);
            }
            else
            {
                generator.AddExtension(crlNumberOid, false, new Org.BouncyCastle.Asn1.DerInteger(0));
            }

            //Получение списка уже отозванных сертификатов
            List<BigInteger> revokedSerialNumbers = GetSerialNumbers(prevCrl);
            //Settings.LoadGoodAndRevoked();
            //Список отозванных сертификатов, которые нужно отозвать сейчас
            IEnumerable<BigInteger> newRevoked = Settings.RevokedCertificateNumbers
                .Except(revokedSerialNumbers);
            //Добавление недавно отозванных сертификатов, в список отзыва
            foreach (BigInteger serialNumber in newRevoked)
            {
                //Причина отзыва не указывается
                generator.AddCrlEntry(serialNumber, DateTime.UtcNow, CrlReason.Unspecified);
            }
            //Формирование CRL
            var crl = generator.Generate(PrivateKey);

            TryWriteFile(Settings.CrlFilePath, crl.GetEncoded(), 100);

            logger.Debug(string.Format(CultureInfo.InvariantCulture, "CRL responce: {0}", Convert.ToBase64String(crl.GetEncoded())));
            return crl;
        }
        else
        {
            return prevCrl;
        }
    }
    else
    {
        X509V2CrlGenerator generator = new X509V2CrlGenerator();
        generator.SetThisUpdate(thisUpdate);
        generator.SetNextUpdate(nextUpdate);
        generator.SetSignatureAlgorithm(Settings.SigningAlgorithm);
        generator.SetIssuerDN(Certificate.SubjectDN);
        generator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(Settings.CACertificate));
        generator.AddExtension(crlNextPublish, false, new Org.BouncyCastle.Asn1.DerUtcTime(nextUpdate));
        generator.AddExtension(crlNumberOid, false, new Org.BouncyCastle.Asn1.DerInteger(0));

        DirectoryInfo revokedCertificateFolder = new DirectoryInfo(Settings.RevokedCertificateFolder);
        IEnumerable<FileInfo> revokedCertificateFiles = revokedCertificateFolder.GetFiles("*.crt");

        foreach (FileInfo revokedCertificateFileInfo in revokedCertificateFiles)
        {
            string name = revokedCertificateFileInfo.Name;
            name = name.Substring(0, name.IndexOf('.'));
            BigInteger serialNumber = new BigInteger(name);
            //Причина отзыва не указывается
            generator.AddCrlEntry(serialNumber, DateTime.UtcNow, CrlReason.Unspecified);
        }

        var crl = generator.Generate(PrivateKey);

        TryWriteFile(Settings.CrlFilePath, crl.GetEncoded(), 100);

        return crl;
    }
}

static List<BigInteger> GetSerialNumbers(X509Crl crl)
{
    List<BigInteger> listNumber = new List<BigInteger>();
    Org.BouncyCastle.Utilities.Collections.ISet revokedCerts = crl.GetRevokedCertificates();
    if (revokedCerts != null)
    {
        foreach (X509CrlEntry crlEntry in revokedCerts)
        {
            listNumber.Add(crlEntry.SerialNumber);
        }
    }
    return listNumber;
}
Sign up to leave a comment.

Articles