Реализация инструмента электронная подписи файлов с использованием КриптоПро ЭЦП Browser plug-in

Реализация инструмента электронная подписи файлов с использованием КриптоПро ЭЦП Browser plug-in ЭЦП

Angular (es modules typescript)

cd examples/angular
npm i

Запуск в режиме разработки:

npm start

Запуск в продакшн режиме:

npm run build
npm run serve

Cryptopro

Единое, асинхронное API для взаимодействия с КриптоПРО ЭЦП Browser Plug-In

React (es modules javascript)

cd examples/react
npm i

Запуск в режиме разработки:

npm start

Запуск в продакшн режиме:

npm run build
npm run serve

Вычисление хэш значения

var CADESCOM_HASH_ALGORITHM_CP_GOST_3411 = 100;

    function run() {
        // Создаем объект CAdESCOM.HashedData
        var oHashedData = cadesplugin.CreateObject("CAdESCOM.HashedData");

        // Алгоритм хэширования нужно указать до того, как будут переданы данные
        oHashedData.Algorithm = CADESCOM_HASH_ALGORITHM_CP_GOST_3411;
        
        // Передаем данные
        oHashedData.Hash("Some data here.");

        // Вычисляем хэш-значение
        var sHashValue1 = oHashedData.Value;
        // Хэш-значение будет вычислено от данных в кодировке UCS2-LE
        // Для алгоритма SHA-1 хэш-значение будет совпадать с вычисленным при помощи CAPICOM
        document.getElementById("hashVal1").innerHTML = sHashValue1;

        // Получение значения свойства oHashedData.Value сбрасывает
        // состояние объекта (алгоритм хэширования остается прежним).
        // Но само значение свойства можно получить несколько раз:
        var sHashValue2 = oHashedData.Value;
        document.getElementById("hashVal2").innerHTML = sHashValue2;

        // То же самое хэш-значение можно получить, если передать данные по частям
        oHashedData.Hash("Some ");
        oHashedData.Hash("data ");
        oHashedData.Hash("here.");
        var sHashValue3 = oHashedData.Value;
        document.getElementById("hashVal3").innerHTML = sHashValue3;
    }

Вычисление хэш значения бинарных данных (его и используем в проекте)

var CADESCOM_HASH_ALGORITHM_CP_GOST_3411 = 100;
    var CADESCOM_BASE64_TO_BINARY = 1;

    function run() {
        // Создаем объект CAdESCOM.HashedData
        var oHashedData = cadesplugin.CreateObject("CAdESCOM.HashedData");

        // Алгоритм хэширования нужно указать до того, как будут переданы данные
        oHashedData.Algorithm = CADESCOM_HASH_ALGORITHM_CP_GOST_3411;

        // Указываем кодировку данных
        // Кодировка должна быть указана до того, как будут переданы сами данные
        oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;

        // Предварительно закодированные в BASE64 бинарные данные
        // В данном случае закодирован файл со строкой "Some Data."
        var dataInBase64 = "U29tZSBEYXRhLg==";

        // Передаем данные
        oHashedData.Hash(dataInBase64);

        // Получаем хэш-значение
        var sHashValue = oHashedData.Value;
        // Это значение будет совпадать с вычисленным при помощи, например,
        // утилиты cryptcp от тех же исходных _бинарных_ данных.
        // В данном случае - от файла со строкой "Some Data."
        
        document.getElementById("hashVal").innerHTML = sHashValue;
    }

Запуск режима разработки

Устанавливаем зависимости:

npm i

Во время работы с кодом необходим запущенный сборщик:

npm start

И пример, на котором можно тестировать изменения.
Удобнее всего тестировать на примере с тэгом script, тк он отвязан от фреймворков
и использует сборку в формате UMD из папки dist/, постоянно обновляемую пока работает
сборщик. Запускаем его таким образом:

cd examples/script-tag
npm i
npm link ../../
npm start

После выполнения npm link ../../ в директории examples/script-tag/node_modules папка crypto-pro станет ярлыком,
указывающим на папку содержащую локально собранный пакет.

Запуск тестов

Тесты написаны с использованием Jest:

npm test

Зачем мне этот пакет?

КриптоПРО ЭЦП Browser Plug-In доступен в разных браузерах в двух версиях.
Асинхронной (в современных браузерах) и синхронной (в браузерах постарше).
С помощью этого пакета можно не писать реализацию под каждую версию плагина дважды.
И вместо этого
и этого
написать это (UMD):

или это (ES Modules Typescript):

Лицензия

MIT

Методы объекта cryptopro

*Методы getContainerCertificates и getAllContainerCertificates позволяют получить сертификаты из закрытых ключей, записанных на обыкновенную флэшку

Методы объекта сертификата

Сертификат предоставляет следущее API:

Миграция с версии 1 на 2

Внесены следующие изменения:

  • Пакет собран в форматах:
    • UMD, в папке dist/, для подключения через тэг script. Объект window.cryptoPro доступен глобально.
    • ES Modules, в папке lib/, для использования с разными системами сборки.
      Методы API импортируются напрямую из npm пакета.
  • В UMD версии переименован глобальный объект с window.CryptoPro на window.cryptoPro
  • Переименованы общие методы:
  • Убран метод signDataXML
  • Переименованы методы сертификата:
  • Результат методов сертификата getOwnerInfo и getIssuerInfo
    изменился с { descr, title, translated } на { description, title, isTranslated }
  • Принципиальная реализация методов, обращающихся к Крипто ПРО не изменилась.
    Получение сертификатов, создание подписи, проверка корректности настроек работают по-прежнему.
  • Убрана поддержка IE8 (Крипто ПРО его больше не поддерживает)
  • Убрана поддержка КриптоПРО CSP версий ниже 4.0
  • Убрана поддержка КриптоПРО ЭЦП browser plug-in версий ниже 2.0
  • Доработана обработка ошибок, выбрасываемых из Крипто ПРО
  • При написании кода будут работать автодополнения и подсказки
  • Исправлена проблема работы библиотеки с UglifyJs
  • Методы API доступны напрямую:

В версии 1:

window.CryptoPro.call('getSystemInfo');

В версии 2 (UMD):

window.cryptoPro.getSystemInfo();

В версии 2 (ES Modules):

import { getSystemInfo } from'crypto-pro';

getSystemInfo();

Настройка плагина для firefox (до версии 52)

После настройки плагина на страницах, запрашивающих работу с ЭП в панели навигации, рядом с url будет кнопка,
позволяющая «разрешить и запомнить» использование установленного плагина.

cd /usr/lib/mozilla/plugins

cp /opt/cprocsp/lib/amd64/libnpcades.so.2.0.0 ./
ldd libnpcades.so.2.0.0

cp /opt/cprocsp/lib/amd64/libnpcades.so.2.0.0 ./libnpcades.so
ldd libnpcades.so

Перезапустите Firefox, и убедитесь в наличии CryptoPRO Cades plugin (см. Menu -> Addons).

Ошибка параметр задан неверно. (0x80070057)

Если при попытке подписать сообщение с использованием PKCS#7 подписи падает такая ошибка, то читайте этот issue

Поддерживаемые скзи

КриптоПРО CSP (v4.0 ) рекомендуется использование только сертифицированных версий. Инструкция по установке:

КриптоПРО ЭЦП browser plug-in (v2.0.12438 ).

Инструкция по установке плагина в Linux. В Windows и OSX следуйте указаниям программы-установщика.

Инструкция по установке сертификатов в систему для Linux / OSX.

Примеры

Для их запуска необходим NodeJS LTS.

Проверка пакета перед публикацией в npm

Необходимо протестировать работу в заявленных браузерах, сделав это на локально запакованной версии пакета.
Для этого собираем пакет:

npm run package
mv package ..

Важно переместить папку package куда-нибудь выше для избежания конфликтов при линковке с текущим package.json.

Переходим в любую директорию с примером и создаем там ссылку на только что собранный пакет:

cd examples/script-tag
npm link ../../../package

Проверяем работу примеров в режимах разработки и продакшн.

После завершения экспериментов можно удалить глобальную ссылку из директории ../../../package таким образом:

cd ../../../package
npm unlink

Проверка работы примеров с react и angular

React и Angular используют версию сборки пакета в формате ES модулей из директории lib/.
Для их запуска необходимо сначала собрать пакет выполнив:

npm run build

После этого из папки examples/angular или examples/react залинковать пакет:

cd examples/angular
npm i
npm link ../../

И запустить пример в одном из двух режимов. В режиме разработки:

npm start

или в режиме продакшн:

npm run build
npm run serve

Расшифровка данных

/**
* Функция расшифровки бинарных данных
* @param EncryptedData шифр
*/
encrypt: function(EncryptedData)
{
    var self = this;
    //Синтаксис языка javascript проверки ошибок, если не удастся создать объект cadescom.CPEnvelopedData
    try {
        // Создаем объект cadescom.CPEnvelopedData
        var oEnvelop = cadesplugin.CreateObject("cadescom.CPEnvelopedData");
    } catch (err) {
        alert('Failed to create CAdESCOM.CPEnvelopedData: '   err.number);
        return;
    }
    // Указываем кодировку данных
    // Кодировка должна быть указана до того, как будут переданы сами данные
    oEnvelop.ContentEncoding = CADESCOM_BASE64_TO_BINARY;
    // Запуск процесса расшифровки данных
    oEnvelop.Decrypt(EncryptedData);
    //В результате расшифровки объект oEnvelop заполнит свойство Content - которое и будет содержать расшифрованные данные
    var sDecriptedData = oEnvelop.Content;
    return sDecriptedData;
},

Тем, кто хочет помочь

Буду благодарен за расширение/улучшение/доработку API.
Вам будут полезны примеры,
предоставляемые Крипто ПРО.

Тэг script (umd)

cd examples/script-tag
npm i
npm start

Установка

Для NPM:

npm install crypto-pro

Для Yarn:

yarn add crypto-pro

Для Bower:

bower install crypto-pro

Подключение пакета как UMD модуля через тэг script:

Установка криптопро csp в linux / osx

Процесс установки в OSX незначительно отличается от Linux, поэтому описание приведено на примере дистрибутива семейства Debian (x64).

Некоторые команды могут потребовать запуска с sudo.
Названия файлов и директорий могут отличаться из-за различий в версиях.

После загрузки КриптоПРО CSP для нужной платформы, распакуйте архив:

tar -xzvf linux-amd64_deb.tgz
chmod 777 -R linux-amd64_deb/

Запустите скрипт установки:

linux-amd64_deb/install.sh

Проверьте отсутствиеcprocsp-rdr-gui:

dpkg -l | grep cprocsp-rdr

Установите дополнительно cprocsp-rdr-gui-gtk:

dpkg -i linux-amd64_deb/cprocsp-rdr-gui-gtk-64_4.0.0-4_amd64.deb

Дополнительная информация по установке

Установка криптопро эцп browser plugin в linux

Загрузите КриптоПРО ЭЦП browser plug-in и распакуйте его:

mkdir cades_linux_amd64
tar -xzvf cades_linux_amd64.tar.gz -C cades_linux_amd64

Сконвертируйте rpm в deb пакеты при помощи утилиты alien:

apt-get update && apt-get install alien
cd cades_linux_amd64
alien *

Установите пакеты:

dpkg -i cprocsp-pki-cades_2.0.0-2_amd64.deb
dpkg -i cprocsp-pki-plugin_2.0.0-2_amd64.deb

Проверьте наличие файлов плагина:

ls -la /opt/cprocsp/lib/amd64 | grep libnpcades

    lrwxrwxrwx 1 root root      19 Окт 21 12:33 libnpcades.so -> libnpcades.so.2.0.0
    lrwxrwxrwx 1 root root      19 Окт 21 12:33 libnpcades.so.2 -> libnpcades.so.2.0.0
    -rwxr-xr-x 1 root root 2727236 Июн  8 14:33 libnpcades.so.2.0.0

Установка сертификатов в linux

В OSX процесс схож с Linux.

Подключите USB носитель с ключевыми контейнерами и проверьте результат команды:

/opt/cprocsp/bin/amd64/csptest -keyset -enum_cont -fqcn -verifyc

    CSP (Type:80) v4.0.9009 KC1 Release Ver:4.0.9797 OS:Linux CPU:AMD64 FastCode:READY:AVX.
        AcquireContext: OK. HCRYPTPROV: 16188003
        \.FLASHivanov
        \.FLASHpetrov
        \.FLASHsidorov
        \.FLASHvasiliev
        \.FLASHsmirnov
        OK.
        Total: SYS: 0,020 sec USR: 0,060 sec UTC: 0,180 sec

Скопируйте ключевой контейнер \.FLASH.sidorov на жесткий диск:

/opt/cprocsp/bin/amd64/csptest -keycopy -contsrc '\.FLASHsidorov' -contdest '\.HDIMAGEsidor'

    CSP (Type:80) v4.0.9009 KC1 Release Ver:4.0.9797 OS:Linux CPU:AMD64 FastCode:READY:AVX.
    CryptAcquireContext succeeded.HCRYPTPROV: 38556259
    CryptAcquireContext succeeded.HCRYPTPROV: 38770755
    Total: SYS: 0,000 sec USR: 0,100 sec UTC: 14,920 sec
    [ErrorCode: 0x00000000]

Наличие [ErrorCode: 0x00000000] в завершении каждой команды КриптоПРО говорит о ее успешном выполнении.

Проверьте наличие нового контейнера \.HDIMAGEsidor:

/opt/cprocsp/bin/amd64/csptest -keyset -enum_cont -fqcn -verifyc

    CSP (Type:80) v4.0.9009 KC1 Release Ver:4.0.9797 OS:Linux CPU:AMD64 FastCode:READY:AVX.
    AcquireContext: OK. HCRYPTPROV: 34554467
    \.FLASHivanov
    \.FLASHpetrov
    \.FLASHsidorov
    \.FLASHvasiliev
    \.FLASHsmirnov
    \.HDIMAGEsidor
    OK.
    Total: SYS: 0,010 sec USR: 0,050 sec UTC: 0,130 sec
    [ErrorCode: 0x00000000]

Установите личный сертификат:

/opt/cprocsp/bin/amd64/certmgr -inst -cont '\.HDIMAGEsidor'

Возможно в выводе вы ссылку на сертификат УЦ

При необходимости загрузите сертификат удостоверяющего центра и установите его командой:

/opt/cprocsp/bin/amd64/certmgr -inst -store uroot -file <файл сертификата>.crt

После чего, при проверке установленного личного сертификата вы увидите PrivateKey Link: Yes:

/opt/cprocsp/bin/amd64/certmgr -list -store uMy

Шифроваение данных

/**
* Функция шифрования бинарных данных
* @param oCertificate выбранный сертификат
* @param data бинарные данные закодированные в base64 строку
*/
encrypt: function(oCertificate, data)
{
    var self = this;
    //Синтаксис языка javascript проверки ошибок, если не удастся создать объект cadescom.CPEnvelopedData
    try {
        // Создаем объект cadescom.CPEnvelopedData
        var oEnvelop = cadesplugin.CreateObject("cadescom.CPEnvelopedData");
    } catch (err) {
        alert('Failed to create CAdESCOM.CPEnvelopedData: '   err.number);
        return;
    }
    // Указываем кодировку данных
    // Кодировка должна быть указана до того, как будут переданы сами данные
    oEnvelop.ContentEncoding = CADESCOM_BASE64_TO_BINARY;
    // Предварительно закодированные в BASE64 бинарные данные
    oEnvelop.Content = data;
    //Установка сертификата для шифрования
    oEnvelop.Recipients.Add(self.Certificate);
    //Получаем зашифрованные данные
    return oEnvelop.Encrypt();
},

Оцените статью
ЭЦП64
Добавить комментарий