Статья посвящена выполненной мной достаточно нетривиальной задаче по интеграции электронной цифровой подписи в веб-шаблоны SAP (Business Explorer Web Application), работающие в SAP NetWeaver. Заранее извиняюсь, если в статье будут допущены ошибки в терминологии или в логике, так как с SAP работаю только 5 месяцев.
Общие сведение об ЭЦП можно получить в википедии ЭЦП
Есть SAP NetWeaver в роли хранилища данных Business Warehouse.
Все данные хранятся в кубах. В кубах же хранятся документы. Документом, по сути, является набор строк куба, имеющих одинаковый признак – номер документа. Работа с данными построена на базе веб-шаблонов Business Explorer Web Application. Содержимое документов отображаются в компоненте analisys item.
Несколько слов для незнакомых с Bex Web. Технология веб-шаблонов (веб форм) по сути напоминает собой ASP.NET. В дизайнере создаешь макет формы, используя компоненты, схожие с ASP (dataGrid, button и прочее). Навешиваешь с помощью мастеров обработчики событий (это могут быть определенные команды или произвольный ABAP код). При запуске веб-формы – она обрабатывается на сервере и клиенты отдается HTML страничка с JS. Реакция на действия пользователя – производиться на стороне сервера при обновлении страницы. В коде веб-шаблона обычно нет необходимости генерировать HTML, как в PHP.
В некой web-форме пользователи вводят данные в таблицу, представленную analisys item. Введенные данные сохраняются в куб. После ввода данных пользователь должен поменять их статус (например, со статуса «Новый» на «Обработано»: перевод статуса происходит с помощью функции repost по значениям признака хранящего статусы данных; этот признак также находится в этом же кубе).
Так вот, необходимо подписывать введенные данные с помощью ЭЦП после ввода/сохранения данных и перед тем, как пользователь переведет эти данные со статуса «Новый» на «Обработано» (подписывать должен тот пользователь, который ввел данные).
Поиск в сети показал, что использовать ЭЦП не так то просто, как хотелось бы. В большинстве стран существуют собственные законодательные акты, регулирующие применение средств криптозащиты. Федеральный закон Российской Федерации от 10 января 2002 г. N 1-ФЗ «Об электронной цифровой подписи»
В частности устанавливаются алгоритмы, которые должны применяться при шифровании и генерации подписи. Например, алгоритм формирования и проверки электронной цифровой подписи ГОСТ Р 34.10-2001
Конечно же, не имеет смысла самим пытаться реализовать данные алгоритмы, поэтому смотрим, что предлагается на рынке.
Например, решения «ЛИССИ»
http://www.lissi.ru/solution/
Позиционируют себя спасителями на белом коне для SAP’овцев.Комплекс софта от них обойдется в сумму, превышающую 300 000 рублей. Программное обеспечение представляет собой API для продуктов SAP, обращаться к которому можно посредством ABAP.
Проблема в том, что данные продукты подразумевают подписание данных посредством кода ABAP. На клиенте же мы имеем только веб-страницу c JS. Исполнить код ABAP можно только на сервере, например с помощью AJAX запроса. Но возникает проблема – закрытый ключ пользователя доступен только на клиенте. Его пересылка на сервер не должна осуществляться. Решение «ЛИССИ» подразумевает работу на клиентской машине полновесного, не тонкого, клиента SAP, в котором возможно выполнение ABAP.
Поэтому я отказался от готовых решений и реализовал ЭЦП через CAPICOM CAPICOM
Здесь описание того, как реализовал ЭЦП
1) Администратор безопасности регистрирует сертификат в базе сертификатов. Сертификат необходимо получить от подлинного удостоверяющего центра.
2) Пользователь работает в системе, создает документ и подписывает его, используя свой секретный ключ на внешнем носителе. При этом:
а) Создается «слепок» документа (выбирается все его содержание).
б) Над содержимом производятся криптографические операции подписания, в результате получаем подпись.
в) Из сертификата подписывающего извлекается отпечаток и сравнивается с отпечатком, зарегистрированным на этого пользователя. В случае совпадения – подпись сохраняется в базе, иначе подпись отменяется.
3) При последующих просмотрах документа, подпись проверяется при открытии документа. Подпись извлекается из БД. Над подписью и содержимым документа проводятся криптографические операции верификации подписи.
4) Администратор безопасности может добавлять сертификаты пользователей в базу сертификатов, приостанавливать временно или постоянно их действие.
Подписи хранятся в плоской таблице «Подписи».

База сертификатов – набор из двух плоских таблиц:

Ключи – собственно сертификаты. В таблице храниться привязанный к ключу пользователь, дата начала и конца действия ключа, сам ключ, статус (блокирован или нет), описание.
Приостановки – набор возможных приостановок действия ключа. Хранит дату начало, конца и описание приостановки. Также хранит ID приостановленного ключа.
Механизм цифровой подписи построен на основе следующих компонентов.
1) ActiveX компонент для доступа к криптографическому API. (CAPICOM)
2) С помощью JS получаем содержимое документа
3) Вызовом метода ActiveX компонента подписать данные.
4) Отправить подпись на сервер (классу ABAP) с целью разместить в базе подписей.

CAPICOM – библиотека от MS, предоставляющая интерфейс к крипто провайдерам.
1 – посредством JS кода, происходят обращения к библиотеке CAPICOM
2 – Веб шаблон формирует данные для подписи (XML, описывающий DataProvider).
3 – Полученная подпись, посредством AJAX передается ABAP классу, осуществляющему сохранение подписи в плоскую таблицу.
4 – взаимодействие крипто провайдера с eToken происходит автоматически.

Класс Signer – реализует пользовательские методы –
Подписать, проверить подпись, получить последнюю подпись
Класс CryptoProvider – враппер для Capicom.
ZCL_AJAX_DIG_SIGN – реализация интерфейсных методов через Ajax.
Z_DIGITAL_SIGNER – реализация методов сохранения и поиска подписи, методов проверки действительности публичного ключа по базе ключей.
Рассмотрим порядок подписания\проверки документа.
Пользователь жмет на форме кнопку «Утвердить(сохранить) документ». JS собирает с с html кода шаблона контент документа, предварительно выгруженный туда. Обращается к CAPICOM, который просит у человека выбрать нужный сертификат. При выборе сертификата сделанного под криптоПро специально для работы в системе – CAPICOM обратиться к провайдеру КриптоПРО, тот же попросит токен с закрытым ключом. Когда токен вставят – контент документа будет подписан. Подпись по AJAX кидается в BSP приложение, оно передает подпись в интерфейсный класс Z_DIGITAL_SIGNER. Класс проверит сертификат из подписи, факт того, что именно такой сертификат привязан к данному залогинившемуся пользователю. В случае успеха проверки – запишет подпись в базу подписей. На форме произойдут изменения – появиться отметка о успешной подписи.
При открытии документа другим пользователем –появиться статус подписания. Это произойдет следующим образом. JS по AJAX запросит подписи для документа, получит подпись (априорно – она сделана нужным человеком и подпись сделана сертификатом из базы разрешенных сертификатов). Затем js дергает CAPICOM — метод «верификация подписи» с параметрами «подпись» и «контент документа». Если с документом и подписью все в порядке – метод вернет true, следовательно, документ подписан и корректен.
Также есть GUI для администратора безопасности – ведение базы активных сертификатов.
1) подключить в XHTML веб шаблона ActiveX компонент CAPICOM, например
Общие сведение об ЭЦП можно получить в википедии ЭЦП
В чем заключалась задача
Есть SAP NetWeaver в роли хранилища данных Business Warehouse.
Все данные хранятся в кубах. В кубах же хранятся документы. Документом, по сути, является набор строк куба, имеющих одинаковый признак – номер документа. Работа с данными построена на базе веб-шаблонов Business Explorer Web Application. Содержимое документов отображаются в компоненте analisys item.
Несколько слов для незнакомых с Bex Web. Технология веб-шаблонов (веб форм) по сути напоминает собой ASP.NET. В дизайнере создаешь макет формы, используя компоненты, схожие с ASP (dataGrid, button и прочее). Навешиваешь с помощью мастеров обработчики событий (это могут быть определенные команды или произвольный ABAP код). При запуске веб-формы – она обрабатывается на сервере и клиенты отдается HTML страничка с JS. Реакция на действия пользователя – производиться на стороне сервера при обновлении страницы. В коде веб-шаблона обычно нет необходимости генерировать HTML, как в PHP.
В некой web-форме пользователи вводят данные в таблицу, представленную analisys item. Введенные данные сохраняются в куб. После ввода данных пользователь должен поменять их статус (например, со статуса «Новый» на «Обработано»: перевод статуса происходит с помощью функции repost по значениям признака хранящего статусы данных; этот признак также находится в этом же кубе).
Так вот, необходимо подписывать введенные данные с помощью ЭЦП после ввода/сохранения данных и перед тем, как пользователь переведет эти данные со статуса «Новый» на «Обработано» (подписывать должен тот пользователь, который ввел данные).
Поиск в сети показал, что использовать ЭЦП не так то просто, как хотелось бы. В большинстве стран существуют собственные законодательные акты, регулирующие применение средств криптозащиты. Федеральный закон Российской Федерации от 10 января 2002 г. N 1-ФЗ «Об электронной цифровой подписи»
В частности устанавливаются алгоритмы, которые должны применяться при шифровании и генерации подписи. Например, алгоритм формирования и проверки электронной цифровой подписи ГОСТ Р 34.10-2001
Конечно же, не имеет смысла самим пытаться реализовать данные алгоритмы, поэтому смотрим, что предлагается на рынке.
Например, решения «ЛИССИ»
http://www.lissi.ru/solution/
Позиционируют себя спасителями на белом коне для SAP’овцев.Комплекс софта от них обойдется в сумму, превышающую 300 000 рублей. Программное обеспечение представляет собой API для продуктов SAP, обращаться к которому можно посредством ABAP.
Проблема в том, что данные продукты подразумевают подписание данных посредством кода ABAP. На клиенте же мы имеем только веб-страницу c JS. Исполнить код ABAP можно только на сервере, например с помощью AJAX запроса. Но возникает проблема – закрытый ключ пользователя доступен только на клиенте. Его пересылка на сервер не должна осуществляться. Решение «ЛИССИ» подразумевает работу на клиентской машине полновесного, не тонкого, клиента SAP, в котором возможно выполнение ABAP.
Поэтому я отказался от готовых решений и реализовал ЭЦП через CAPICOM CAPICOM
Реализация ЭЦП
Здесь описание того, как реализовал ЭЦП
1 Порядок применения ЭЦП
1) Администратор безопасности регистрирует сертификат в базе сертификатов. Сертификат необходимо получить от подлинного удостоверяющего центра.
2) Пользователь работает в системе, создает документ и подписывает его, используя свой секретный ключ на внешнем носителе. При этом:
а) Создается «слепок» документа (выбирается все его содержание).
б) Над содержимом производятся криптографические операции подписания, в результате получаем подпись.
в) Из сертификата подписывающего извлекается отпечаток и сравнивается с отпечатком, зарегистрированным на этого пользователя. В случае совпадения – подпись сохраняется в базе, иначе подпись отменяется.
3) При последующих просмотрах документа, подпись проверяется при открытии документа. Подпись извлекается из БД. Над подписью и содержимым документа проводятся криптографические операции верификации подписи.
4) Администратор безопасности может добавлять сертификаты пользователей в базу сертификатов, приостанавливать временно или постоянно их действие.
2 Реализация хранения данных
Подписи хранятся в плоской таблице «Подписи».

База сертификатов – набор из двух плоских таблиц:

Ключи – собственно сертификаты. В таблице храниться привязанный к ключу пользователь, дата начала и конца действия ключа, сам ключ, статус (блокирован или нет), описание.
Приостановки – набор возможных приостановок действия ключа. Хранит дату начало, конца и описание приостановки. Также хранит ID приостановленного ключа.
3 Архитектура системы цифровой подписи
Механизм цифровой подписи построен на основе следующих компонентов.
1) ActiveX компонент для доступа к криптографическому API. (CAPICOM)
2) С помощью JS получаем содержимое документа
3) Вызовом метода ActiveX компонента подписать данные.
4) Отправить подпись на сервер (классу ABAP) с целью разместить в базе подписей.

CAPICOM – библиотека от MS, предоставляющая интерфейс к крипто провайдерам.
1 – посредством JS кода, происходят обращения к библиотеке CAPICOM
2 – Веб шаблон формирует данные для подписи (XML, описывающий DataProvider).
3 – Полученная подпись, посредством AJAX передается ABAP классу, осуществляющему сохранение подписи в плоскую таблицу.
4 – взаимодействие крипто провайдера с eToken происходит автоматически.
4 Реализация API

Класс Signer – реализует пользовательские методы –
Подписать, проверить подпись, получить последнюю подпись
Класс CryptoProvider – враппер для Capicom.
ZCL_AJAX_DIG_SIGN – реализация интерфейсных методов через Ajax.
Z_DIGITAL_SIGNER – реализация методов сохранения и поиска подписи, методов проверки действительности публичного ключа по базе ключей.
5 Дополнительно словесное описание
Рассмотрим порядок подписания\проверки документа.
Пользователь жмет на форме кнопку «Утвердить(сохранить) документ». JS собирает с с html кода шаблона контент документа, предварительно выгруженный туда. Обращается к CAPICOM, который просит у человека выбрать нужный сертификат. При выборе сертификата сделанного под криптоПро специально для работы в системе – CAPICOM обратиться к провайдеру КриптоПРО, тот же попросит токен с закрытым ключом. Когда токен вставят – контент документа будет подписан. Подпись по AJAX кидается в BSP приложение, оно передает подпись в интерфейсный класс Z_DIGITAL_SIGNER. Класс проверит сертификат из подписи, факт того, что именно такой сертификат привязан к данному залогинившемуся пользователю. В случае успеха проверки – запишет подпись в базу подписей. На форме произойдут изменения – появиться отметка о успешной подписи.
При открытии документа другим пользователем –появиться статус подписания. Это произойдет следующим образом. JS по AJAX запросит подписи для документа, получит подпись (априорно – она сделана нужным человеком и подпись сделана сертификатом из базы разрешенных сертификатов). Затем js дергает CAPICOM — метод «верификация подписи» с параметрами «подпись» и «контент документа». Если с документом и подписью все в порядке – метод вернет true, следовательно, документ подписан и корректен.
Также есть GUI для администратора безопасности – ведение базы активных сертификатов.
Подключение ЭЦП к веб-шаблону
1) подключить в XHTML веб шаблона ActiveX компонент CAPICOM, например
- <object id="CapicomObj" codebase="bwmimerep:///sap/bw/mime/Customer/JS/bin/capicom.cab" classid="clsid:A996E48C-D3DC-4244-89F7-AFA33EC60679" VIEWASTEXT="" />
* This source code was highlighted with Source Code Highlighter.
2) Создать новый провайдер данных с тем же запросом, что и основной. То есть, сделать копию провайдера. Таким образом получим выгруженный документ в HTML, который будем подписывать. Нельзя подписывать провайдер, который выводит документ в таблицу пользователя, потому что, при сортировки или фильтрации таблицы — данные в провайдеры будут меняться, а нам нужен документ в начальном виде.
3) Разместить на форме компонент «провайдер данных-информация».
Назовем его DATA_PROVIDER_TO_SIGN.

Синим- компонент «провайдер данных-информация», красным — он же в палитре компонентов, желтым — провайдер данных, поставляющий контент документа
4) Укажем в настройках DATA_PROVIDER_TO_SIGN:
Провайдер данных: Укажем созданную в шаге 2 копию провайдера.
Статус навигации — вывод: Off
Данные отчета: вывод: On
5) Размещаем на форме код
Здесь уже все зависит от вашей фантазии. Не буду постить ВЕСЬ свой код, включающий AJAX, ABAP, JavaScript, оставлю только простенький врапер для CAPICOM, который я сделал на основе примеров с сайта Microsoft.
- function CryptoProvider(OBJECT1)
- {
- // CAPICOM constants
- //Const to verify
- CryptoProvider.prototype.CAPICOM_ACTIVE_DIRECTORY_USER_STORE = 3;
- CryptoProvider.prototype.CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_DESCRIPTION = 2;
- CryptoProvider.prototype.CAPICOM_AUTHENTICATED_ATTRIBUTE_DOCUMENT_NAME = 1;
- CryptoProvider.prototype.CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME = 0;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY = 7;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_CERTIFICATE_POLICY = 8;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY = 6;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_EXTENSION = 5;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_ISSUER_NAME = 2;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_KEY_USAGE = 12;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_ROOT_NAME = 3;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME = 4;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_TIME_EXPIRED = 11;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_TIME_NOT_YET_VALID = 10;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_FIND_TIME_VALID = 9;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT = 0;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY = 2;
- CryptoProvider.prototype.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN = 1;
- CryptoProvider.prototype.CAPICOM_CURRENT_USER_STORE = 2;
- CryptoProvider.prototype.CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE = 0x00000080;
- CryptoProvider.prototype.CAPICOM_E_CANCELLED = -2138568446;
- CryptoProvider.prototype.CAPICOM_ENCODE_ANY = 0xffffffff;
- CryptoProvider.prototype.CAPICOM_ENCODE_BASE64 = 0;
- CryptoProvider.prototype.CAPICOM_ENCODE_BINARY = 1;
- CryptoProvider.prototype.CAPICOM_INFO_SUBJECT_SIMPLE_NAME = 0;
- CryptoProvider.prototype.CAPICOM_KEY_STORAGE_DEFAULT = 0;
- CryptoProvider.prototype.CAPICOM_LOCAL_MACHINE_STORE = 1;
- CryptoProvider.prototype.CAPICOM_PROPID_KEY_PROV_INFO = 2;
- CryptoProvider.prototype.CAPICOM_SMART_CARD_USER_STORE = 4;
- CryptoProvider.prototype.CAPICOM_STORE_OPEN_READ_ONLY = 0;
- CryptoProvider.prototype.CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE = 1
- CryptoProvider.prototype.CAPICOM_VERIFY_SIGNATURE_ONLY = 0;
- CryptoProvider.prototype.CERT_KEY_SPEC_PROP_ID = 6;
-
-
- //CryptoProvider.prototype.CertThumbprint = "";
- CryptoProvider.prototype.CertValue = "";
- CryptoProvider.prototype.CertHash = "";
- CryptoProvider.prototype.ErrorStack = "";
- CryptoProvider.prototype.ErrorState = 0;
- CryptoProvider.prototype.VerifySert = false;
-
- CryptoProvider.prototype.oCAPICOM = OBJECT1;
-
- //CryptoProvider.prototype.Init();
- }
-
- // объявляем, инициализируем, реализуем свойства и методы
-
- CryptoProvider.prototype.IsCAPICOMInstalled = function ()
- {
- if (typeof (this.oCAPICOM) == "object")
- {
- if ((this.oCAPICOM.object != null))
- {
- //alert(" We found CAPICOM!");
- return true;
- }
- }
- }
-
- CryptoProvider.prototype.Init = function ()
- {
- var FilteredCertificates = this.FilterCertificates();
- if (FilteredCertificates)
- {
- if (FilteredCertificates.Count == 1)
- {
- this.CertValue = FilteredCertificates.Item(1).GetInfo(this.CAPICOM_INFO_SUBJECT_SIMPLE_NAME);
- this.CertHash = FilteredCertificates.Item(1).Thumbprint;
- }
- else
- {
- this.CertValue = "";
- this.CertHash = "";
- this.SelectCertificate(FilteredCertificates);
- }
- FilteredCertificates = null;
- }
- else
- {
- this.ErrorStack += "У Вас нет действующих сертификатов.\n";
- this.ErrorState = 13;
- }
- }
-
-
- CryptoProvider.prototype.FilterCertificates = function ()
- {
- var MyStore = new ActiveXObject("CAPICOM.Store");
- var FilteredCertificates = new ActiveXObject("CAPICOM.Certificates");
- try
- {
- //MyStore.Open(this.CAPICOM_CURRENT_USER_STORE, "My", this.CAPICOM_STORE_OPEN_READ_ONLY);
- MyStore.Open(this.CAPICOM_CURRENT_USER_STORE, "MY");
- }
- catch (e)
- {
- if (e.number != this.CAPICOM_E_CANCELLED)
- {
- this.ErrorStack += "Ошибка при открытии хранилища сертификатов.\n";
- this.ErrorState = 11;
- return false;
- }
- }
- // find all of the certificates that:
- // * Are good for signing data
- // * Have PrivateKeys associated with then - Note how this is being done :)
- // * Are they time valid
- //var FilteredCertificates = MyStore.Certificates.Find(this.CAPICOM_CERTIFICATE_FIND_KEY_USAGE, this.CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE).Find(this.CAPICOM_CERTIFICATE_FIND_TIME_VALID).Find(this.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, this.CERT_KEY_SPEC_PROP_ID);
- var FilteredCertificates = MyStore.Certificates.Find(this.CAPICOM_CERTIFICATE_FIND_KEY_USAGE, this.CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE).Find(this.CAPICOM_CERTIFICATE_FIND_TIME_VALID).Find(this.CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY, this.CERT_KEY_SPEC_PROP_ID);
- //var FilteredCertificates = MyStore.Certificates.Find(this.CAPICOM_CERTIFICATE_FIND_KEY_USAGE, this.CAPICOM_DIGITAL_SIGNATURE_KEY_USAGE).Find(this.CAPICOM_CERTIFICATE_FIND_TIME_VALID);
- return FilteredCertificates;
- MyStore = null;
- FilteredCertificates = null;
- }
-
- CryptoProvider.prototype.FindCertificateByHash = function (szThumbprint)
- {
- // instantiate the CAPICOM objects
- var MyStore = new ActiveXObject("CAPICOM.Store");
- // open the current users personal certificate store
- try
- {
- MyStore.Open(this.CAPICOM_CURRENT_USER_STORE, "My", this.CAPICOM_STORE_OPEN_READ_ONLY);
- }
- catch (e)
- {
- if (e.number != this.CAPICOM_E_CANCELLED)
- {
- this.ErrorStack += "Ошибка при открытии хранилища сертификатов.\n";
- this.ErrorState = 12;
- return false;
- }
- }
-
- // find all of the certificates that have the specified hash
- var FilteredCertificates = MyStore.Certificates.Find(this.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, szThumbprint);
- return FilteredCertificates.Item(1);
-
- // Clean Up
- MyStore = null;
- FilteredCertificates = null;
- }
-
- CryptoProvider.prototype.SelectCertificate = function (Serts)
- {
- var ret;
- var FilteredCertificates = Serts;
- try
- {
- // Pop up the selection UI
- var SelectedCertificate = FilteredCertificates.Select();
- if (SelectedCertificate)
- {
- this.CertValue = SelectedCertificate.Item(1).GetInfo(this.CAPICOM_INFO_SUBJECT_SIMPLE_NAME); ;
- this.CertHash = SelectedCertificate.Item(1).Thumbprint;
- ret = true;
- }
- else
- {
- this.CertValue = "";
- this.CertHash = "";
- this.ErrorStack += "Вы не выбрали сертификат.\n";
- this.ErrorState = 20;
- ret = false;
- }
- }
- catch (e)
- {
- this.CertValue = "";
- this.CertHash = "";
- this.ErrorStack += e.description + "\n";
- this.ErrorState = 19;
- ret = false;
- }
- SelectedCertificate = null;
- FilteredCertificates = null;
- return ret;
- }
-
- CryptoProvider.prototype.SignedData = function (toSign)
- {
- // instantiate the CAPICOM objects
- var SignedData = new ActiveXObject("CAPICOM.SignedData");
- var Signer = new ActiveXObject("CAPICOM.Signer");
- var TimeAttribute = new ActiveXObject("CAPICOM.Attribute");
- // only do this if the user selected a certificate
- if (this.CertHash != "")
- {
- try
- {
- if (toSign == "")
- {
- throw new userException('Отсутствуют данные для подписи.');
- }
- SignedData.Content = toSign;
- // Set the Certificate we would like to sign with
- Signer.Certificate = this.FindCertificateByHash(this.CertHash);
-
- // Set the time in which we are applying the signature
- var Today = new Date();
- TimeAttribute.Name = this.CAPICOM_AUTHENTICATED_ATTRIBUTE_SIGNING_TIME;
- TimeAttribute.Value = Today.getVarDate();
- Today = null;
- Signer.AuthenticatedAttributes.Add(TimeAttribute);
- // Do the Sign operation
- var szSignature = SignedData.Sign(Signer, true, this.CAPICOM_ENCODE_BASE64);
- }
-
- catch (e)
- {
- if (e.number != this.CAPICOM_E_CANCELLED)
- {
- this.ErrorStack += "Ошибка доступа к подписываемому содержимому: " + e.description + "\n";
- this.ErrorState = 10;
- return "";
- }
- else
- {
- this.ErrorStack += e.description + "\n";
- this.ErrorState = 15;
- return "";
- }
- }
- return szSignature;
- }
- else
- {
- this.ErrorStack += 'Не был выбран сертификат.\n';
- this.ErrorState = 16;
- return "";
- }
- }
-
- CryptoProvider.prototype.VerifySig = function (toVer, sign)
- {
- // instantiate the CAPICOM objects
- var SignedData = new ActiveXObject('CAPICOM.SignedData');
- try
- {
- SignedData.Content = toVer;
- var mode;
- this.VerifySert ? mode = this.CAPICOM_VERIFY_SIGNATURE_AND_CERTIFICATE : mode = this.CAPICOM_VERIFY_SIGNATURE_ONLY;
- SignedData.Verify(sign, true, mode);
- }
- catch (e)
- {
- this.ErrorStack += e.description + "\n";
- return false;
- }
- return true;
- }
* This source code was highlighted with Source Code Highlighter.
И пример его использования
Подписание
- SignerProv = new CryptoProvider(this.CapicomObj);
- if (SignerProv.IsCAPICOMInstalled())
- {
- SignerProv.Init();
- Sign== SignerProv.SignedData(DataToSign);
- }
* This source code was highlighted with Source Code Highlighter.
Проверка подписи
- SignerProv = new CryptoProvider(this.CapicomObj);
- SignerProv.VerifySert = true;//false – если не надо проверять сам сертификат на подлинность
- if (SignerProv.IsCAPICOMInstalled())
- {
- var SRes = SignerProv.VerifySig(ContentToVerif, SignToVerify);
- }
* This source code was highlighted with Source Code Highlighter.