В комментариях к статье «Использование механизмов криптографических токенов PKCS#11 в скриптовых языках» читатель kovserg написал:
В итоге мы представляем на суд пользователей утилиту
Движущей силой этой утилиты является криптографический токен PKCS#11 c поддержкой российской криптографии как минимум ГОСТ Р 34.10-2012. Если вы собираетесь пользоваться госуслугами и т.п., то необходимо приобрести все же токен, выдерживший сертифицированные испытания в системе сертификации ФСБ России. Если это ваш внутренний электронный документооборот, то это, естественно, на ваше усмотрение. Токены PKCS#11 могут быть разные: программные, аппаратные и даже облачные. Утилита написана на скриптовом языке Tcl/Tk. Когда вы приобретаете токен PKCS#11 не забудьте получить или поинтересоваться, где можно скачать библиотеки для приобретаемого токена для тех или иных платформ. Библиотеки, как правило, находятся в свободном доступе. Для доступа к криптографическим и другим возможностях токена в утилите используется пакет TclPKCS11. Работа утилиты начинается с выбора библиотеки, которая поддерживает ваши токены. Отметим, что библотеки могут поддерживать одновременно работу с несколькими токенами (combobox «выберите токен/смаркарту»):
Может возникнуть вопрос, а что делать, если токен не проинициализирован или требуется поменять PIN-коды и т.д.? Ответ простой – воспользоваться утилитой конфигурирования токенов p11conf.
Для обновления списка токенов (отключили токен, добавили новый) достаточно щелкнуть
по иконке , находящейся справа от combobox-а «Выберите токен/смарткарту»
В combox-е «Сертификат» представлены метки всех сертификатов, хранящихся на выбранном (текущем) токене:
Если нажать на иконку , находящуюся справа от combobox-а «Сертификат», то появится окно с содержимым сертификата:
Если нажать на кнопку «Save/Сохранить» в окне просмотра, то содержимое разобранного сертификата в текстовом формате будет сохранено в указанном вами файле.
Для просмотра информации о текущем токене можно нажать кнопку « 6. Информация на токене» или подвести курсор на метку токена:
Для того, чтобы узнать, какие криптографические механизмы поддерживает текущий токен, достаточно нажать на кнопку « 5. Список механизмов»:
Сообщение «Токен не поддерживает ключи …» появляется в том случае, если выбранный токен не поддерживает генерацию данного типа ключа. В этом случае необходимо выбрать другой тип ключа или другой токен. В данном примере можно использвать токен RuToken ECP 2.0 (см. второй скриншот). Combobox «Владелец сертификата» позволяет указать кому будет принадлежать сертификат: физическому лицу, юридическому лицу или индивидуальному предпринимателю. В зависимости от этого будут формироваться на следующих страницах поля для заполнения.
Значимым полем здесь является поле «Наименование СКЗИ». Оно является неотъемлемой частью квалифицированного сертификата и указывает на то, каким СКЗИ будет сгенерирована ключевая пара. Наименование СКЗИ вы можете узнать в формуляре на изделие или в момент приобретения токена. Совпадает ли поле тип в информации о токене с наименованием СКЗИ, я затрудняюсь сказать. Так что лучше посмотреть формуляр. Нажимаем кнопку Next и заполняем требуемые поля:
При заполнении утилита старается контролировать правильность заполнения полей (email, ОГРН и т.п.), выдавая соответствующие предупреждения. После заполнения основных полей будет предложено определиться с форматом и местом хранения на вашем компьютере запроса на сертификата. От вас также потребуется ввести PIN-код вашего токена:
После нажатия кнопки «Next» вам будет предложено еще раз взглянуть на то, что вы ввели, и утвердить ваше решение нажатием клавиши «Finish»:
И, если вы нажмете кнопку «Finish», то на вашем токене будет сгенерирована ключевая пара, создан и подписан запрос:
А можно убедиться, что ключи сгенерированы и сохранены на токене? Да. Нажимаем кнопку « 7. Объекты токена», вводим PIN-код для доступа к токену и ищем объекты СКО_PRIVATE_KEY и CKO_PUBLIV_KEY, у которых метки совпадают с полем «COMMON NANE» (CN), которое вы заполнили при создании запроса на сертификат. В нашем примере это было «Всесильный Хабр»:
Посмотрели и сразу уходите на другую страницу. Лучшим доказательством, что ключевая пара успешно создана, является наличие самого подписанного запроса. Для того чтобы убедиться в этом нажимаем кнопку «Просмотр запроса/сертификата», выбираем сохраненный запрос, нажимаем кновку «Просмотр запроса на сертификат» и смотрим информацию о ключевой паре:
После того как убедились, что запрос успешно создан, надежно прячем токен с закрытым ключом или кладем поближе к сердцу (люди старшего поколения знают, как хранили партийный или комсомольский билеты), копируем запрос на флэшку, берем необходимые документы (паспорт и т.д) и идем в УЦ для получения сертификата. Да, если это не ведомственный УЦ, то еще придется заплатить деньги. Все как с паспортом.
После выпуска сертификата сотрудник УЦ экспортирует выпущенный сертификат на флэшку Достопочтенного Хабра:
И вот счастливый обладатель сертификата возвращается в родные пенаты и первым делом решает положить сертификат на токен рядом с ключевой парой. Для этого на главном окне утилиты нажимаем кнопку « 4. Просмотр запроса/сертификата», выбираем файл с сертификатом и операцию «Просмотр сертификата» и нажимаем кнопку выполнить операцию»:
Мы можем также проверить валидность сертификата (но мы еще не успели его отозвать) или корректность его подписи, выбрав соответствующую операцию:
Но нас сейчас интересует операция импорта полученного сертификата на наш токен. Выбираем операцию «Импорт сертификата на токен» и нажимаем кнопку «Выполнить операцию». Утилита проверит электронную подпись сертификата. Для этого от вас потребуется ввести PIN-код к токену. И если все пройдет нормально, то сертификат будет импортирован на токен:
Метку (nickname ) сертификата можно будет лицезреть в списке сертификатов:
Это наш личный сертификат, сертификат для которого есть ключевая пара. И если еще раз просмотреть список объектов на токене, то мы найдем три объекта, имеющую метку «Всесильный Хабр from УЦ 12_512» и одинаковые CKA_ID. Этими тремя объектами являются сам сертификат (CKO_CERTIFICATE), открытый (CKO_PUBLIC_KEY) и закрытый (CKO_PRIVATE_KEY) ключи. Метка для этой тройки объектов устанавливается следующим образом:
<CN владельца сертификат> from <CN издателя сертификата>.
Ниже мы покажем как изменить метку.
Теперь, когда мы положили сертификат на токен, как получить доступ к нему? Для того, чтобы получить доступ к функциям работы с сертификатами, находящимися на токене, достаточно подвести курсор на метку «Сертификат» и нажать правую кнопку мыши:
Дождемся следующей статьи. Ждать придется пару дней. Что там еще будет рассмотрено можно понять из скриншота:
Продолжение здесь.
«С нетерпением ждём статью с функцией подписания документа и добавлением метки времени».Еще раньше другой участник хабра pas писал о том, что было бы здорово для токенов PKCS#11, «которые сами все умеют считать» (имеются ввиду прежде всего криптографические операции по генерации ключей, формирования и проверки электронной), избавиться от всевозможных прослоек и иметь одну утилиту, которая могла бы, используя механизмы самого токена, и формировать запрос на сертификат, и подписывать документы, проверять подпись документов, проверять подпись и валидность сертификатов.
Знакомство с утилитой
В итоге мы представляем на суд пользователей утилиту
Движущей силой этой утилиты является криптографический токен PKCS#11 c поддержкой российской криптографии как минимум ГОСТ Р 34.10-2012. Если вы собираетесь пользоваться госуслугами и т.п., то необходимо приобрести все же токен, выдерживший сертифицированные испытания в системе сертификации ФСБ России. Если это ваш внутренний электронный документооборот, то это, естественно, на ваше усмотрение. Токены PKCS#11 могут быть разные: программные, аппаратные и даже облачные. Утилита написана на скриптовом языке Tcl/Tk. Когда вы приобретаете токен PKCS#11 не забудьте получить или поинтересоваться, где можно скачать библиотеки для приобретаемого токена для тех или иных платформ. Библиотеки, как правило, находятся в свободном доступе. Для доступа к криптографическим и другим возможностях токена в утилите используется пакет TclPKCS11. Работа утилиты начинается с выбора библиотеки, которая поддерживает ваши токены. Отметим, что библотеки могут поддерживать одновременно работу с несколькими токенами (combobox «выберите токен/смаркарту»):
Может возникнуть вопрос, а что делать, если токен не проинициализирован или требуется поменять PIN-коды и т.д.? Ответ простой – воспользоваться утилитой конфигурирования токенов p11conf.
Для обновления списка токенов (отключили токен, добавили новый) достаточно щелкнуть
по иконке , находящейся справа от combobox-а «Выберите токен/смарткарту»
В combox-е «Сертификат» представлены метки всех сертификатов, хранящихся на выбранном (текущем) токене:
Если нажать на иконку , находящуюся справа от combobox-а «Сертификат», то появится окно с содержимым сертификата:
Если нажать на кнопку «Save/Сохранить» в окне просмотра, то содержимое разобранного сертификата в текстовом формате будет сохранено в указанном вами файле.
Для просмотра информации о текущем токене можно нажать кнопку « 6. Информация на токене» или подвести курсор на метку токена:
Для того, чтобы узнать, какие криптографические механизмы поддерживает текущий токен, достаточно нажать на кнопку « 5. Список механизмов»:
Создаем запрос на сертификат
Переходим к основным функциям утилиты. И первой такой функцией является создание запроса на сертификат (кнопка « 3. Запрос на сертификат»):Сообщение «Токен не поддерживает ключи …» появляется в том случае, если выбранный токен не поддерживает генерацию данного типа ключа. В этом случае необходимо выбрать другой тип ключа или другой токен. В данном примере можно использвать токен RuToken ECP 2.0 (см. второй скриншот). Combobox «Владелец сертификата» позволяет указать кому будет принадлежать сертификат: физическому лицу, юридическому лицу или индивидуальному предпринимателю. В зависимости от этого будут формироваться на следующих страницах поля для заполнения.
Значимым полем здесь является поле «Наименование СКЗИ». Оно является неотъемлемой частью квалифицированного сертификата и указывает на то, каким СКЗИ будет сгенерирована ключевая пара. Наименование СКЗИ вы можете узнать в формуляре на изделие или в момент приобретения токена. Совпадает ли поле тип в информации о токене с наименованием СКЗИ, я затрудняюсь сказать. Так что лучше посмотреть формуляр. Нажимаем кнопку Next и заполняем требуемые поля:
При заполнении утилита старается контролировать правильность заполнения полей (email, ОГРН и т.п.), выдавая соответствующие предупреждения. После заполнения основных полей будет предложено определиться с форматом и местом хранения на вашем компьютере запроса на сертификата. От вас также потребуется ввести PIN-код вашего токена:
После нажатия кнопки «Next» вам будет предложено еще раз взглянуть на то, что вы ввели, и утвердить ваше решение нажатием клавиши «Finish»:
И, если вы нажмете кнопку «Finish», то на вашем токене будет сгенерирована ключевая пара, создан и подписан запрос:
А можно убедиться, что ключи сгенерированы и сохранены на токене? Да. Нажимаем кнопку « 7. Объекты токена», вводим PIN-код для доступа к токену и ищем объекты СКО_PRIVATE_KEY и CKO_PUBLIV_KEY, у которых метки совпадают с полем «COMMON NANE» (CN), которое вы заполнили при создании запроса на сертификат. В нашем примере это было «Всесильный Хабр»:
Посмотрели и сразу уходите на другую страницу. Лучшим доказательством, что ключевая пара успешно создана, является наличие самого подписанного запроса. Для того чтобы убедиться в этом нажимаем кнопку «Просмотр запроса/сертификата», выбираем сохраненный запрос, нажимаем кновку «Просмотр запроса на сертификат» и смотрим информацию о ключевой паре:
После того как убедились, что запрос успешно создан, надежно прячем токен с закрытым ключом или кладем поближе к сердцу (люди старшего поколения знают, как хранили партийный или комсомольский билеты), копируем запрос на флэшку, берем необходимые документы (паспорт и т.д) и идем в УЦ для получения сертификата. Да, если это не ведомственный УЦ, то еще придется заплатить деньги. Все как с паспортом.
Отправляемся за сертификатом в УЦ
В данном случае для выдачи сертификата достопочтенному Хабру, мы воспользуемся УЦ со страниц все тоже Хабра. УЦ начинает рассмотрение нашей заявки:
После того как заявка поступила в базу данных УЦ, уполномоченный администратор рассматривает ее и либо отклоняет либо утверждает:
После утверждения заявки заявитель вместе с уполномоченным лицом от УЦ определяют цели использования сертификата:
И после этого уже ничто не мешает выпуску сертификата:
После того как заявка поступила в базу данных УЦ, уполномоченный администратор рассматривает ее и либо отклоняет либо утверждает:
После утверждения заявки заявитель вместе с уполномоченным лицом от УЦ определяют цели использования сертификата:
И после этого уже ничто не мешает выпуску сертификата:
После выпуска сертификата сотрудник УЦ экспортирует выпущенный сертификат на флэшку Достопочтенного Хабра:
Кладем сертификат на токен
И вот счастливый обладатель сертификата возвращается в родные пенаты и первым делом решает положить сертификат на токен рядом с ключевой парой. Для этого на главном окне утилиты нажимаем кнопку « 4. Просмотр запроса/сертификата», выбираем файл с сертификатом и операцию «Просмотр сертификата» и нажимаем кнопку выполнить операцию»:
Мы можем также проверить валидность сертификата (но мы еще не успели его отозвать) или корректность его подписи, выбрав соответствующую операцию:
Код утилиты проверки подписи сертификата
#!/usr/bin/env tclsh
package require pki
load ./tclpkcs11.so Tclpkcs11
#Задайте путь к вашей библиотеке PKCS#11
#set pkcs11_module "/usr/local/lib64/librtpkcs11ecp_2.0.so"
set pkcs11_module "/usr/local/lib64/libls11sw2016.so"
puts "Connect the Token and press Enter"
gets stdin yes
set handle [pki::pkcs11::loadmodule $pkcs11_module]
set slots [pki::pkcs11::listslots $handle]
set i 0
foreach slotinfo $slots {
set slotid [lindex $slotinfo 0]
set slotlabel [lindex $slotinfo 1]
set slotflags [lindex $slotinfo 2]
if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} {
set token_slotlabel $slotlabel
set token_slotid $slotid
#Найден слот с токеном
incr i
break
}
}
if {$i == 0} {
puts "Нет ни одного токена. Вставьте."
exit
}
#Из PEM в DER
proc ::cert_to_der {data} {
if {[string first "-----BEGIN CERTIFICATE-----" $data] != -1} {
set data [string map {"\r\n" "\n"} $data]
}
array set parsed_cert [::pki::_parse_pem $data "-----BEGIN CERTIFICATE-----" "-----END CERTIFICATE-----"]
if {[string range $parsed_cert(data) 0 0 ] == "0" } {
#Очень похоже на DER-кодировка "0" == 0x30
set asnblock $parsed_cert(data)
} else {
set asnblock ""
}
return $asnblock
}
proc usage {use error} {
puts "Copyright(C) Orlov Vladimir (http://museum.lissi-crypto.ru/) 2019"
if {$use == 1} {
puts $error
puts "Usage:\nverify_cert_with_pkcs11 <file with certificate> \[<file with CA certificate>\]\n"
}
}
set countcert [llength $argv]
if { $countcert < 1 || $countcert > 2 } {
usage 1 "Bad usage!"
exit
}
set file [lindex $argv 0]
if {![file exists $file]} {
usage 1 "File $file not exist"
exit
}
#Проверяемый сертификат cert_user
puts "Loading user certificate: $file"
set fd [open $file]
chan configure $fd -translation binary
set cert_user [read $fd]
close $fd
if {$cert_user == "" } {
usage 1 "Bad file with certificate user: $file"
exit
}
set cert_user [cert_to_der $cert_user]
if {$cert_user == ""} {
puts "User certificate bad"
exit
}
catch {array set cert_parse [::pki::x509::parse_cert $cert_user]}
if {![info exists cert_parse]} {
puts "User certificate bad"
exit
}
#parray cert_parse
if {$countcert == 1} {
if {$cert_parse(issuer) != $cert_parse(subject)} {
puts "Bad usage: not self signed certificate"
} else {
set cert_CA $cert_user
}
} else {
set fileca [lindex $argv 1]
if {![file exists $fileca]} {
usage 1 "File $fileca not exist"
exit
}
#Сертификат издателя cert_CA
puts "Loading CA certificate: $fileca"
set fd [open $fileca]
chan configure $fd -translation binary
set cert_CA [read $fd]
close $fd
if {$cert_CA == "" } {
usage 1 "Bad file with certificate CA=$fileca"
exit
}
set cert_CA [cert_to_der $cert_CA]
if {$cert_CA == ""} {
puts "CA certificate bad"
exit
}
}
foreach slotinfo $slots {
set slotid [lindex $slotinfo 0]
set slotlabel [lindex $slotinfo 1]
set slotflags [lindex $slotinfo 2]
if {[lsearch -exact $slotflags TOKEN_PRESENT] != -1} {
set token_slotlabel $slotlabel
set token_slotid $slotid
}
}
#Ключ от корневого сертификата
catch {array set cert_parse_CA [::pki::x509::parse_cert $cert_CA]}
if {![info exists cert_parse_CA]} {
puts "CA certificate bad"
exit
}
#Проверяем издателя
if {$cert_parse(issuer) != $cert_parse_CA(subject)} {
puts "Bad issuer"
exit
}
set aa [dict create pkcs11_handle $handle pkcs11_slotid $token_slotid]
set tbs_cert [binary format H* $cert_parse(cert)]
catch {set signature_algo_number [::pki::_oid_name_to_number $cert_parse(signature_algo)]}
if {![info exists signature_algo_number]} {
set signature_algo_number $cert_parse(signature_algo)
}
switch -- $signature_algo_number {
"1.2.643.2.2.3" - "1 2 643 2 2 3" {
# "GOST R 34.10-2001 with GOST R 34.11-94"
set digest_algo "gostr3411"
}
"1.2.643.7.1.1.3.2" - "1 2 643 7 1 1 3 2" {
# "GOST R 34.10-2012-256 with GOSTR 34.11-2012-256"
set digest_algo "stribog256"
}
"1.2.643.7.1.1.3.3" - "1 2 643 7 1 1 3 3" {
# "GOST R 34.10-2012-512 with GOSTR 34.11-2012-512"
set digest_algo "stribog512"
}
default {
puts "Неизвестная алгоритм подписи:$signature_algo_number"
exit
}
}
#Посчитать хэш от tbs-сертификата!!!!
set digest_hex [pki::pkcs11::digest $digest_algo $tbs_cert $aa]
#Получаем asn-структуру публичного ключа
#Создаем список ключевых элементов
binary scan $cert_CA H* cert_CA_hex
array set infopk [pki::pkcs11::pubkeyinfo $cert_CA_hex [list pkcs11_handle $handle pkcs11_slotid $token_slotid]]
set lpk [dict create pkcs11_handle $handle pkcs11_slotid $token_slotid]
#Добавляем pybkeyinfo в список ключевых элементов
lappend lpk "pubkeyinfo"
lappend lpk $infopk(pubkeyinfo)
array set lpkar $lpk
puts "Enter PIN user for you token \"$token_slotlabel\":"
gets stdin password
if { [pki::pkcs11::login $handle $token_slotid $password] == 0 } {
puts "Bad PIN"
exit
}
if {[catch {set verify [pki::pkcs11::verify $digest_hex $cert_parse(signature) $lpk]} res] } {
puts "Ошибка проверки подписи=$res"
exit
}
if {$verify != 1} {
puts "BAD SIGNATURE=$verify"
} else {
puts "SIGNATURE OK=$verify"
}
Но нас сейчас интересует операция импорта полученного сертификата на наш токен. Выбираем операцию «Импорт сертификата на токен» и нажимаем кнопку «Выполнить операцию». Утилита проверит электронную подпись сертификата. Для этого от вас потребуется ввести PIN-код к токену. И если все пройдет нормально, то сертификат будет импортирован на токен:
Метку (nickname ) сертификата можно будет лицезреть в списке сертификатов:
Это наш личный сертификат, сертификат для которого есть ключевая пара. И если еще раз просмотреть список объектов на токене, то мы найдем три объекта, имеющую метку «Всесильный Хабр from УЦ 12_512» и одинаковые CKA_ID. Этими тремя объектами являются сам сертификат (CKO_CERTIFICATE), открытый (CKO_PUBLIC_KEY) и закрытый (CKO_PRIVATE_KEY) ключи. Метка для этой тройки объектов устанавливается следующим образом:
<CN владельца сертификат> from <CN издателя сертификата>.
Ниже мы покажем как изменить метку.
Теперь, когда мы положили сертификат на токен, как получить доступ к нему? Для того, чтобы получить доступ к функциям работы с сертификатами, находящимися на токене, достаточно подвести курсор на метку «Сертификат» и нажать правую кнопку мыши:
Подписываем электронной подписью первый документ
Дождемся следующей статьи. Ждать придется пару дней. Что там еще будет рассмотрено можно понять из скриншота:
Продолжение здесь.