Инфраструктура открытых ключей (продолжение): удостоверяющий центр на базе утилиты OpenSSL и SQLite3

    imageЕсли одним из главных объектов инфраструктуры открытых ключей (ИОК) являются сертификаты X509, то центральным субъектом ИОК являются Удостоверяющие Центры (УЦ). Именно УЦ выпускают сертификаты, прекращают их действие (отзыв сертификата), подтверждают их валидность. На страницах Хабрахабр можно найти различные публикации на тему выпуска цифровых сертификатов с использованием OpenSSL. В основном в этих статьях рассматривается применение утилиты openssl, описывается ее интерфейс командной строки и работа с файлами, в которых хранится все: ключи, запросы, сертификаты, в том числе и корневой и т.д. Но если разрабатывать полномасштабный удостоверяющий центр (УЦ) на базе OpenSSL, то естественным является желание избавится от этого многообразия файлов и перейти к работе с базами данных, а также иметь графический интерфейс для выпуска сертификатов и управления ими. А если вспомнить Федеральный Закон от 6 апреля 2011г. №63-ФЗ «Об электронной подписи», то необходимо, чтобы УЦ соответствовал требованиям этого закона, а также «Требованиям к форме квалифицированного сертификата ключа проверки электронной подписи», утвержденных приказом ФСБ России от 27.12.2011 № 795.

    У простых граждан создается впечатление, что УЦ это что-то громадное (как же, Центр, почти как Центр Управления Полетами).

    imageС точки зрения ответственности УЦ – это именно так. Ведь сертификаты, выпускаемые УЦ, фактически сегодня приравнены в паспорту.

    С программистской точки зрения, все не так страшно. Так родился проект удостоверяющего центра CAFL63. Реализация проекта CAFL63 базируется на трех «китах», а именно OpenSSL, SQLite3 и Tcl/Tk.

    Итак, что же такое Удостоверяющий Центр сегодня? Прежде всего это Центр Регистрации, куда с пакетом необходимых документов, частности, удостоверяющих личность и полномочия заявителя, приходят за сертификатами представители юридический лиц, физические лица, индивидуальные предпринимателей. Они могут приходить с готовыми заявками в электронном виде. В ЦР проверяют документы, запрос (заполненные данные, корректность электронной подписи и т.д), и, если все прошло успешно принимают запрос, утверждают его и передают в Центр Сертификации (ЦС). Но это в идеале. На практике, все выглядит по-другому.

    Гражданам, организациям нужен сертификат (для доступа на портал Госуслуг, для сдачи налогой отчетности, для участия в торгах), но они не знают что это такое и что с ним делать. Они искренне убеждены, что в УЦ получают электронную подпись типа факсимиле. Но это проблемы просвещения. Поэтому заявители приходят в ЦР УЦ, предъявляют документы. Вместе с сотрудником ЦР идут на отдельное рабочее место и готовят запрос на сертификат.



    Подготовленный запрос на электронном носителе, о чем уже говорилось, поступает в ЦР. Что нужно помнить заявителю? Первое и главное забрать носитель с созданным закрытым ключом!
    Утвержденный запрос на электронном носителе передается в ЦС, где на его основе и будет выпущен сертификат.

    Это принципиальная схема работы УЦ. Детали станут понятны ниже. Одно замечание, в целях удобства демонстрации утилита подготовки запроса, ЦР и ЦС объединены в один демонстрационный комплекс. Но никаких проблем с разнесением функционала нет. Самый простой из них, это на каждом рабочем месте иметь по экземпляру CAFL63 и задействовать только требуемый функционал.

    Когда реализация проекта шла полным ходом, на глаза попался проект SimpleCA. Изучение этого проекта очень помогло при окончательной реализации УЦ CAFL63.

    В состав дистрибутива для платформ Win32/Win64, Linux_x86/Linux_x86_64 помимо исходного кода CAFL63 входит и файл README.txt. После скачивания дистрибутива следует внимательно прочитать файл README.txt.

    Итак, запускаем утилиту CAFL63 и на экране появляется стартовая страница:



    Работу мы начинаем с нажатия клавиши «Создать БД». База данных УЦ создается средствами кроссплатформенной СУБД SQLite3. БД УЦ содержит несколько таблиц. Главная таблица mainDB содержит всего одну запись, в которой хранится корневой сертификат, закрытый ключ, зашифрованный на пароле, и настройки УЦ. Есть две таблицы, связанные с запросами на сертификаты: текущие запросы reqDB и архив запросов reqDBArc. Для сертификатов создается три таблицы: таблица новых сертификатов certDBNew, таблица архива сертификатов certDB и таблица отозванных сертификатов certDBRev:

    . . . 
    certdb eval {create table certDB(  ckaID text primary key ,  
                   nick text,  sernum text,  certPEM text, subject text, 
                    notAfter text,  notBefore text, dateRevoke text,  state text )}
    certdb eval {create table certDBRev( ckaID text primary key )}
    certdb eval {create table certDBNew( ckaID text primary key )}
    certdb eval {create table reqDB (ckaID text primary key, nick  text,  
                        sernum text, subject text, type text, datereq text, status text, reqpem text,
                        pkcs7 text)}
    certdb eval {create table reqDBAr (ckaID text primary key, nick  text,  sernum text, 
                 subject text, type text, datereq text, status text, reqpem text, pkcs7 text)}
    certdb eval {create table crlDB(ID integer primary key autoincrement, signtype text, 
                   issuer text, publishdate text, nextdate text, crlpem text)}
    . . .

    Все таблицы запросов и сертификатов в качестве ключа (primary key) используют значение хэш (sha1) от открытого ключа. Для удобства в дальнейшем значение хэш от значения открытого ключа будем называть CKAID (терминология PKCS#11). Это оказалось очень удобным, например, при поиске сертификата по запросу или наоборот. В БД есть еще одна таблица crlDB, в которой хранятся списки отозванных сертификатов.

    Значение открытого ключа хранится как в запросе, так и в сертификате. Поэтому, прежде чем положить их в БД, необходимо извлечь из них открытый ключ и вычислить CKAID. Для извлечения значения открытого ключа удобно воспользоваться пакетом pki (package require pki), который содержит средства для работы с сертификатами и запросами. Однако этот пакет не рассчитан на работу с российской криптографией. В связи с этим на базе входящих в пакет pki процедур parse_cert и parse_csr написать процедуры parce_cert_gost и parse_csr_gost:

    ...
    	## Convert Pubkey type to string
    	set pubkey_type [::pki::_oid_number_to_name $pubkey_type]
    	# Parse public key, based on type
    	switch -- $pubkey_type {
    		"rsaEncryption" {
    			set pubkey [binary format B* $pubkey]
    			binary scan $pubkey H* ret(pubkey)
    			::asn::asnGetSequence pubkey pubkey_parts
    				::asn::asnGetBigInteger pubkey_parts ret(n)
    				::asn::asnGetBigInteger pubkey_parts ret(e)
    			set ret(n) [::math::bignum::tostr $ret(n)]
    			set ret(e) [::math::bignum::tostr $ret(e)]
    			set ret(l) [expr {int([::pki::_bits $ret(n)] / 8.0000 + 0.5) * 8}]
    			set ret(type) rsa
    		}
    		"1.2.643.2.2.19" -
    		"1.2.643.7.1.1.1.1" -
    		"1.2.643.7.1.1.1.2" {
    #	gost2001, gost2012-256,gost2012-512
    			set pubkey [binary format B* $pubkey]
    			binary scan $pubkey H* ret(pubkey)
    			set ret(type) $pubkey_type
    			::asn::asnGetSequence pubkey_algoid pubalgost
    #OID - параметра
    			::asn::asnGetObjectIdentifier pubalgost oid1
    #OID - Функция хэша
    			::asn::asnGetObjectIdentifier pubalgost oid2
    		}
    		default {
    			error "Unknown algorithm"
    		}
    	}
    ...

    В отличии от «родных» процедур, они позволяют работать с объектами не только в формате PEM, но и в формате DER. Для работы со списками отозванных сертификатов CRL была написана процедура parse_crl. Все эти процедуры можно найти в исходном коде, который хранится вместе с дистрибутивом.

    Также в пакете pki отсутствуют и российские oid-ы, например, ИНН, СНИЛС и т.д. Эта проблема лекго решается путем добавления российских oid-ов в массив ::pki::oids:

    . . . 
        set ::pki::oids(1.2.643.100.1)  "OGRN"
        set ::pki::oids(1.2.643.100.5)  "OGRNIP"
        set ::pki::oids(1.2.643.3.131.1.1) "INN"
        set ::pki::oids(1.2.643.100.3) "SNILS"
    #Алгоритмы подписи
        set ::pki::oids(1.2.643.2.2.3) "ГОСТ Р 34.10-2001"
        set ::pki::oids(1.2.643.7.1.1.3.2) "ГОСТ Р 34.10-2012-256"
        set ::pki::oids(1.2.643.7.1.1.3.3) "ГОСТ Р 34.10-2012-512"
    . . .

    Имея функции parse_cert_gost и parse_csr_gost, значения CKAID (primary key для БД) вычисляется следующим образом:

    . . .
        array    set b [parse_csr_gost $req]
        set pem $b(pem)
        set subject $b(subject)
        set pubkey $b(pubkey)
        set key1 [binary format H* $pubkey]
        set ckaID [::sha1::sha1 $key1]
    . . . 

    Итак, нажимаем кнопку «Создать БД»:



    Создание УЦ начинается с выбора каталога, в котором будем хранить БД и задания пароля для доступа к закрытому ключу УЦ. Утилита CAFL63 внимательно следит за длиной пароля:



    Пароль хранится в БД УЦ в виде хэша:

    . . .
    set hash256 [::sha2::sha256 $wizData(capassword)]
    . . . 

    После нажатия клавишы «Next» начинается процесс формирования самоподписанного корневого сертификата разворачиваемого УЦ. На первом шаге этого процесса выбирается тип и параметры ключевой пары:



    Определившись с ключевой парой для корневого сертификата создаваемого удостоверяющего центра, мы приступаем к заполнению формы информацией о владельце (первый скриншот пропущен).

    Отметим, что утилита CAFL63 обладает определенным «интеллектом» и поэтому контролирует не только наличие данных в полях, но и правильность (красная подсветка — неправильно) заполнения таких полей как ИНН, ОГРН, СНИЛС, ОГРНИП, адрес электронной почты и др.:



    После заполнения полей информацией о владельце УЦ будет предложено определиться с системными настройками УЦ:



    Если вы не собираетесь работать с российской криптографией, то можете использовать обычный OpenSSL. Для работы с российской криптографией, необходимо выбрать соответствующую версию, модификацию OpenSSL. Более подробно читайте README.txt в скаченном дистрибутиве. Поскольку предполагается выпуск квалифицированных сертификатов, то необходимо также дать информацию о сертификации самого УЦ и используемом им СКЗИ (см. «Требования к форме квалифицированного сертификата ключа проверки электронной подписи», утвержденные приказом ФСБ России от 27.12.2011 № 795).

    После правильного заполнения всех полей, еще раз будет предложено проверить их достоверность и нажать кнопку «Finish»:



    После нажатия кнопки «Finish» будет создана БД УЦ, в которой будут сохранены корневой сертифкат УЦ, закрытый ключ, системные настройки, и на экране вновь появится стартовая страница утилиты CAFL63. Теперь, когда у нас создана база данных вновь создаваемого УЦ, мы нажимаем кнопку «Открыть БД», выбираем каталог с БД, попадаем в главное рабочее окно УЦ и нажав кнопку «Просмотр CA УЦ», убеждаемся, что тот корневой сертификат, который мы создали:



    Следующим шагом мы подготавливаем шаблоны/профили заявок для юридический лиц, физических лиц, индивидуальных предпринимателей (Средства->Настройки->Типы Сертификатов->Новый ):



    После задания имени нового профиля будет предложено определить его состав:



    Состав профиля определяет distinguished name (отличительное/уникальное имя владельца сертификата). Каждого профиль имеет свой состав с обязательными (required) или нет полями/oid-ами. Состав профиля для юридический лиц, физических лиц, индивидуальных предпринимателей определяется требованиями ФЗ-63 и «Требованиями к форме квалифицированного сертификата ключа проверки электронной подписи» ФСБ России.

    После подготовки профилей УЦ готов к приему заявителей и заявок от них. Как было отмечено выше, заявитель может приходить как с готовой заявкой на сертификат, так и без нее.
    Если заявитель пришел с готовой заявкой, то после проверки его документов, заявка импортируется в БД УЦ. Для этого необходимо на главном рабочем окне выбрать вкладку «Запросы на сертификаты», нажать кнопку «Импорт запроса/CSR» и выбрать файл с запросом. После этого появится окно с информацией о запросе:



    Просмотрев запрос и убедившись в его правильном заполнении можно нажимать кнопку «Import» для занесения его в базу данных. Сразу отметим, что при попытке повторного внесения запроса в БД УЦ будет выдано сообщение:



    Запросы в БД УЦ помечаются (колонка «Type») либо как «Locale», созданные в центре регистрации УЦ, либо как «Import», созданные самим заявителем, а также фиксируется время поступления заявки в УЦ. Это может оказаться полезным при разборе конфликтных ситуаций. Поэтому при импорте запроса на сертификат следует указывать кем был создан запрос (см. скриншот).
    Импортированная заявка находится в БД УЦ и отображается на главном окне на вкладке «Запросы на сертификаты». Поступившие запросы находятся в стадии «рассмотрения» (колонка «Status» вкладки «Запросы на сертификат» и «Архив Запросов» ). По каждому вновь поступившему запросу должно быть принято решение (выпадающее меню при нажатии правой клавиши мышки на выбранном запросе):



    Каждый запрос должен быть или отклонен или утвержден:



    Если запрос отклоняется, то он перемещается из таблицы текущих запросов reqDB в таблицу архива запросов reqDBArc и, соответсвенно, исчезает на вкладке «Запросы на сертификаты» и появляется на вкладке «Архив Запросов».

    Утвержденная заявка остается в таблице reqDB и на вкладке «Запросы на сертификаты» до выпуска сертификата, а потом тоже попадает в архив.

    Перед выпуском сертификата надо вмесе с заявителем уточнить для каких целей (например, для доступа на портал Госуслуг ) будет использоваться сертификат (Средства->Настройки->Типы Сертификатов ->Физ.лицо ->Редактировать ->Key Usage):



    Для выпуска сертификата надо выбрать утвержденную заявку на вкладке «Запросы на сертификаты», нажать правую клавишу мыши и в выпадающем меню при выбрать пункт «Выпустить сертификат». В появившемся виджете необходимо будет выбрать профиль, которому должен соответствовть профиль запроса/сертификата:



    Отметим, что в процессе выпуска сертифиата можно уточнить значения того или иного поля:



    Сама процедура выпуска сертификата (пункт меню «Выпустить сертификат») мало отличается от процедуры создания корневого сертификата или выпуска заявки:



    Выпущенный сертификат сразу же появлется на вкладке «Сертификаты». При этом сам сертификат попадает в таблицу certDBNew БД УЦ и остается там до тех пор, пока он не будет опубликован. Сертификат считается опубликованным после его экспорта в SQL-дамп новых сертификатов, который передается на публичный сервис. Опубликование сертификата приводит к перемещению его из таблицы certDBNew в таблицу certDB.

    Если нажать правую клавишу мыши на выбранной строке в закладке «Сертификаты», то появится меню с функциями:



    Эти функции позволяют просмотреть как сам сертификат, так и запрос, на основании которого он был выпущен. Можно также экспортировать сертификат в файл или на флэшку заявителя. Важнейшей функцией здесь является функция отзыва сертификата! Есть и такая экзотическая функция как экспорт сертификата в защищенный контейнер PKCS#12. Он используется, когда заявитель хочет получить такой контейнер. Для таких заявителей специально предусмотрена функция генерации запроса с сохранением закрытого ключа в файле (кнопка «Создать запрос/CSR» на вкладке «Запросы на сертификаты» ).

    Итак, УЦ начал свою жизнь, выпустил первый сертификат. Одна из задач УЦ – это организация свободного доступа к выпускаемым сертификатам. Публикация сертификатов как правило идет через Web-сервисы. Естьтакой сервис и у CAFL63:



    Для публикации сертификатов и списков отозванных сертификатов на публичном сервисе УЦ предварительно выгружает сертификаты или в файлы (Сертификаты->Экспорт сертификатов), либо делает SQL –дамп всей таблицы сертификатов, из которой можно создать БД сертификатов и загрузить в нее их, а в последующем делать SQL-дамп новых сертификатов, из которого они будут добавляться в БД публичного сервиса:



    Последний скриншот сделан на платформе Windows и наглядно демонстрирует кросплатформенность БД УЦ: она была просто скопирована с платформы Linux.
    Основополагающая функция УЦ – это публикация списка отозванных сертификатов по аналогии с тем, как это делает МВД относительно утративших силу паспортов. Сертификат может быть отозван по заявлению владельца. Основной причиной отзыва является утрата закрытого ключа или потеря доверия к нему.

    Для отзыва сертификата достаточно выбрать его на вкладке «Сертификаты», нажать правую кнопку мыши и выбрать пункт меню «Отзыв сертификата»:



    Процедура отзыва не отличается от процедуры утверждения запроса или выпуска сертификата. Отозванный сертификат попадает в таблицу cerDBRev базы данных УЦ и появляется во вкладке «Отозванные сертификаты».

    Осталось рассмотреть последнюю функцию УЦ – выпуск CRL — списка отозванных сертификатов. Список CRL формируется на вкладке «Отозванные сертификаты» при нажатии кнопки «Создать СОС/CRL». Все, что требуется от администратора, это ввести пароль УЦ и подтвердить свое намерение выпустить CRL:



    Выпущенный CRL попадает в таблицу crlDB базы данных и отображается на вкладке «CRL/СОС».

    Для разбора CRL перед его помещением в БД была написана процедура parse_crl:

    proc parse_crl {crl} {
        array set ret [list]
        if { [string range $crl 0 9 ] == "-----BEGIN" } {
    	array set parsed_crl [::pki::_parse_pem $crl "-----BEGIN X509 CRL-----" "-----END X509 CRL-----"]
    	set crl $parsed_crl(data)
        }
        ::asn::asnGetSequence crl crl_seq
    	::asn::asnGetSequence crl_seq crl_base
    	    ::asn::asnGetSequence crl_base crl_full
    		::asn::asnGetObjectIdentifier crl_full ret(signtype) 
    #puts "KEY_TYPE=$ret(signtype)"	    
    	    ::::asn::asnGetSequence crl_base crl_issue
    		set ret(issue) [::pki::x509::_dn_to_string $crl_issue]
    #puts "ISSUE=$ret(issue)"    
    	    ::asn::asnGetUTCTime crl_base ret(publishDate)
    	    ::asn::asnGetUTCTime crl_base ret(nextDate)
    #puts "publishDate=$ret(publishDate)"    
        return [array get ret]
    }

    Для просмотра CRL или его экспорта с целью публикации на публичном сервисе необходимо как всегда выбрать нужную строку, нажать правую кнопку мыши и выбрать пункт меню:



    Вот и все, Удостоверяющий Центр готов.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 18
    • 0
      А дистрибутив с исходниками?
      • +2

        Виноват. Дистрибутив и исходники утилиты находятся здесь.

        • 0

          Коллега garex прислал ссылки как получить openssl с ГОСТ-ами:


          Но сегодня в стандартной версии openssl отсутствует поддержка как ГОСТ Р 34.11-2012, так и ГОСТ Р 34.10-2012. Более того в версии 1.1 поддержка криптографии ГОСТ исключена из стандартной поставки («The GOST engine was out of date and therefore it has been removed.»).
          Чем не устраивает вот эта, которую "убрали?" https://github.com/gost-engine/engine
          Пример билда: https://github.com/rnixik/docker-openssl-gost/blob/master/Dockerfile

          Я скачал, скомпилировал вместе с engine, подключил к CAFL63. Все замечательно работает. Есть отдельные недочеты, например, при просмотре сертификатов/запросов не отображаются отдельные поля, введенные ТК-26 (Issuer Sign Tool, Subject Sign Tool и т.п.):



          но это дело наживное.
          Спасибо, garex !

        • 0
          А для чего проверяется факт присутствия открытого ключа в БД?
          • 0

            Не совсем понял о каком открытом ключе в БД идет речь. Все открытые ключи "хранятся" в сертификатах. Собственно открытые ключи используются для прямого доступа (CKAID) к запросам на сертификат, к сертификатам. Подскажите о чем идет речь.

            • 0
              Я говорю вот про этот скриншот:
              image
              • +1

                Теперь все ясно. Здесь речь идет (и это не догма, а просто мое мнение и не более того), чтобы каждый сертификат/запрос имел уникальный ключ. Это позволяет избегать многих недоразумений. И эта проверка легко отключается.

                • 0
                  Я вот как раз и хотел спросить, как реализовано сопоставление публичных ключей. Как минимум для RSA это задача не совсем тривиальная.
                  • 0

                    Я только чтосегодня вернулся, поэтому может до меня не все сразу доходит: в чем нетравиальность задачи для RSA?

                    • +1
                      В том, что можно сделать как минимум два с виду разных открытых ключа для одного закрытого и наоборот — два закрытых для одного открытого. Достаточно для этого добавить λ(n) к экспоненте.
                      • +2

                        Я думаю решение этой задачи для RSA можно найти в проекте XCA, рассмотрев функцию findUniqueID(CKO_PUBLIC_KEY). Функция находится в файле pkcs11.cpp.

          • 0
            Мнение диванного эксперта.
            Если решили обходится спартанским интерфейсом, то стоило сразу делать на чем то в стиле ncurses, чтобы по ssh в консоли работало.
            • +3

              Проблем с ncurses, естественно, нет:


              Для создания/редактирования файла конфигурации и управления ПАК «SMS-FW» используется утилита smsconf. Данная утилита позволяет администратору системы редактировать файл конфигурации и управлять работой комплекса как локально, с внутреннего сервера, так и удаленно, со своего рабочего места, используя протокол telnet или защищенный протокол ssh для связи с внутренним сервером ПАК «SMS-FW».
              Утилита smsconf имеет псевдографический интерфейс и разработана с использованием библиотеки ncurses и функционирует в среде ОС Linux:

              Проблем с ssh, в том числе и ГОСТ-овым ssh, тоже нет.
              Есть проблемы, точнее требования законодательства (тоже ФЗ-63) и требования регулятора (ФСБ, ФСТЭК России). В соответствии с ними УЦ не должен иметь выхода во внешний мир. Поэтому речи об ssh здесь и не может быть. А интерфейс все же проще писать (если это не командная строка) на виджетах да и работать на них все же приятней.

              • +1
                Тогда зачет!
                • 0

                  Тогда спасибо за поддержку

              • +1
                А чем плох спартанский интерфейс? Все просто, ясно и понятно.
                • 0
                  Если захочется на сервере поднять и с внешки подключиться для управления. Но автор уже прояснил этот момент выше.
              • 0

                С победными реляциями я поторопился по поводу openssl и gost-engine. К сожалению выпустить квалифицированный сертификат с этой версией openssl и gost-engine не удастся, не хватает обрабтки требуемых oid-ов:


                Error Loading extension section cert_ext
                140436202112768:error:22097081:X509 V3 routines:do_ext_nconf:unknown extension:crypto/x509v3/v3_conf.c:82:
                140436202112768:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:crypto/x509v3/v3_conf.c:47:name=issuerSignTool, value=@issuer_sign_tool_section

                Надо дорабатывать!

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое