Интеграция ЭЦП НУЦ РК в информационные системы на базе веб технологий
- среда, 8 июля 2020 г. в 00:31:50
Я расскажу о тонкостях внедрения электронной цифровой подписи (ЭЦП) в информационные системы (ИС) на базе веб технологий в контексте Национального Удостоверяющего Центра Республики Казахстан (НУЦ РК).
В центре внимания будет формирование ЭЦП под электронными документами и, соответственно, NCALayer — предоставляемое НУЦ РК криптографическое программное обеспечение. В частности уделю внимание вопросам связанным с UX и объемом поддерживаемого функционала NCALayer.
Процесс разделю на следующие этапы:
Разработчикам важно понимать то, что любое изменение подписанного документа приведет к тому, что подпись под ним перестанет проходить проверку. При этом изменения могут быть вызваны не только редактированием самих данных документа, но и обновлением структуры документа или механизма его сериализации.
Рассмотрим простой пример — документы хранятся в виде записей в базе данных. Для подписания документа необходимо сформировать его представление в виде единого блока данных (конечно можно подписывать каждое поле записи поотдельности, но обычно так не делают), сделать это можно, к примеру, следующими способами:
Далее возможны два сценария каждый из которых имеет свои подводные камни:
В том случае, если ИС не хранит сформированного представления, разработчикам необходимо гарантировать что в будущем формируемые представления будут бинарно идентичны тем, которые были сформированы в первый раз не смотря на:
В том случае, если на каком-то этапе бинарная идентичность перестанет соблюдаться, то проверки цифровых подписей перестанут выполняться и юридическая значимость документов в ИС будет утеряна.
Подход с хранением сформированного представления в базе данных ИС надежнее с точки зрения обеспечения сохранности юридической значимости, но и тут есть нюанс — необходимо гарантировать эквивалентность данных в подписанном документе данным в записи в базе данных иначе может возникнуть такая ситуация когда ИС принимает решение (выполняет расчет) на основании информации не соответствующей тому, что было подписано. То есть нужно либо так же, как и в предыдущем случае, обеспечивать бинарную идентичность формируемого представления, тогда при проверках в первую очередь следует формировать представление из текущего содержимого записи в базе данных и бинарно сравнивать новое представление с сохраненным. Либо необходим механизм позволяющий разобрать сохраненное сформированное представление и сравнить данные из него с текущим содержимым записи в базе данных. Этот механизм так же придется дорабатывать постоянно параллельно с доработками основного функционала ИС.
Для формирования цифровых подписей на стороне клиента НУЦ РК предоставляет единственный инструмент — сертифицированное программное обеспечение NCALayer которое представляет из себя WebSocket сервер, запускаемый на 127.0.0.1
, которому можно отправлять запросы на выполнение криптографических (а так же некоторых смежных) операций. При выполнении некоторых операций NCALayer отображает диалоговые окна — то есть берет часть работы по получению пользовательского ввода на себя.
Описание API NCALayer доступно в составе комплекта разработчика. Для того, чтобы поэкспериментировать со взаимодействием с NCALayer по WebSocket можно воспользоваться страницей интерактивной документации KAZTOKEN mobile (KAZTOKEN mobile повторяет API NCALayer).
Взаимодействовать с NCALayer из браузера можно напрямую с помощью класса WebSocket, либо можно воспользоваться библиотекой ncalayer-js-client которая оборачивает отправку команд и получение ответов в современные async
вызовы.
Замечу что весь основной функционал NCALayer доступен в модуле kz.gov.pki.knca.commonUtils
, использовать модуль kz.gov.pki.knca.applet.Applet
(наследие Java аплета) не рекомендую, так как, на мой взгляд, это не даст никаких преимуществ, но шансов выстрелить себе в ногу с ним больше — к примеру можно случайно разработать интерфейс который не будет поддерживать аппаратных носителей (токенов или смарт-карт) с несколькими ключевыми парами.
Модуль kz.gov.pki.knca.commonUtils
берет на себя взаимодействие с пользователем связанное с выбором конкретного хранилища, которое нужно использовать для выполнения операции (так же он берет на себя выбор конкретного сертификата и соответствующего ключа, а так же ввод пароля или ПИН кода), но ему необходимо указать какой тип хранилищ нужно использовать. Типы хранилищ стоит разделить на два класса:
'PKCS12'
,getActiveTokens
.Таким образом для того, чтобы предоставить пользователю возможность работать с любым поддерживаемым NCALayer хранилищем, можно воспользоваться одним из следующих подходов:
getActiveTokens
, в ответ получить массив имен доступных а данный момент типов хранилищ, добавить в него 'PKCS12'
и спросить у пользователя каким он хотел бы в данный момент воспользоваться;getActiveTokens
, в том случае, если он вернул массив несколькими именами, попросить пользователя отключить лишнее, если в массиве один элемент, использовать его, если массив пустой, использовать 'PKCS12'
.Для подписания данных рекомендую использовать следующие запросы (опять же чтобы снизить вероятность выстрела в ногу):
createCAdESFromBase64
— вычислить подпись под данными и сформировать CMS (CAdES);createCMSSignatureFromBase64
— вычислить подпись под данными, получить на подпись метку времени (TSP) и сформировать CMS (CAdES) с внедренной меткой времени;signXml
— вычислить подпись под XML документом, сформированную подпись добавить в результирующий документ (XMLDSIG); signXmls
— аналогично signXml
, но позволяет за один раз подписать несколько XML документов.В качестве параметров каждому из них нужно будет передать тип хранилища, тип сертификата, подписываемые данные и дополнительные модификаторы.
Модуль kz.gov.pki.knca.commonUtils
поддерживает следующие типы сертификатов:
'AUTHENTICATION'
— сертификаты для выполнения аутентификации;'SIGNATURE'
— сертификаты для подписания данных.NCLayer предоставит пользователю выбирать только из тех сертификатов, которые соответствуют указанному типу.
Упрощенный пример подписания произвольного блока данных с использованием ncalayer-js-client:
async function connectAndSign(base64EncodedData) {
const ncalayerClient = new NCALayerClient();
try {
await ncalayerClient.connect();
} catch (error) {
alert(`Не удалось подключиться к NCALayer: ${error.toString()}`);
return;
}
let activeTokens;
try {
activeTokens = await ncalayerClient.getActiveTokens();
} catch (error) {
alert(error.toString());
return;
}
const storageType = activeTokens[0] || NCALayerClient.fileStorageType;
let base64EncodedSignature;
try {
base64EncodedSignature = await ncalayerClient.createCAdESFromBase64(storageType, base64EncodedData);
} catch (error) {
alert(error.toString());
return;
}
return base64EncodedSignature;
}
Тема проверки цифровых подписей обширна и я не планировал раскрывать ее в этот раз, но упомянуть о необходимости выполнения проверок как с технической, так и юридической точки зрения счел необходимым.
С технической точки зрения проверка цифровой подписи на стороне сервера в первую очередь гарантирует целостность полученного документа, во вторую — авторство, а так же неотказуемость. То есть даже в том случае, если ИС получает подписанный документ не напрямую от пользователя, а через какие-то дополнительные слои программного обеспечения, уверенность в том, что было получено именно то, что отправлял пользователь сохраняется. Поэтому в ситуации когда подписание на стороне клиента реализовано, а возможность проверки подписи на стороне сервера отсутствует, внедрение цифровой подписи теряет смысл.
С юридической точки зрения ориентироваться следует на Приказ Министра по инвестициям и развитию Республики Казахстан “Об утверждении Правил проверки подлинности электронной цифровой подписи”. В Приказе перечислены необходимые проверки которые должны выполнять информационные системы для обеспечения юридической значимости подписанных электронной цифровой подписью документов. Анализу этого документа, а так же некоторым техническим вопросам посвящена заметка Проверка цифровой подписи.
Выполнять проверки необходимо с применением сертифицированных средств, к примеру с помощью библиотек входящих в состав комплекта разработчика НУЦ РК, либо можно воспользоваться готовым решением SIGEX.
Проверка подписи под электронным документом включает в себя проверку срока действия сертификата и проверку статуса отозванности сертификата. В том случае, когда необходимо обеспечить юридическую значимость подписанного документа по истечению срока действия сертификата или в том случае, когда сертификат был отозван через некоторое время после подписания, следует собирать дополнительный набор доказательств фиксирующий момент подписания и подтверждающий то, что на момент подписания сертификат не истек и не был отозван.
Для фиксации момента подписания принято использовать метки времени TSP. Метку времени на подпись можно получить либо на клиенте (запрос createCMSSignatureFromBase64
интегрирует метку времени в CMS), либо на сервере. Метка времени позволит удостовериться в том, что момент подписания попадает в срок действия сертификата.
Для того, чтобы удостовериться в том, что сертификат не был отозван в момент подписания, следует использовать CRL или OCSP ответ. Этот нюанс и рекомендации по реализации описаны в разделе APPENDIX B — Placing a Signature At a Particular Point in Time документа RFC 3161.