Электронная цифровая подпись на сайте при помощи КриптоПро ЭЦП Browser plug-in / Хабр

Почему не работает крипто про эцп браузер плагин

Если после перехода на портал разработчика при проверке расширения появляется статус «Недоступен», значит настройки в веб-обозревателе сделаны неправильно. Установите их вновь. Если опять отобразится аналогичное уведомление, то почистите кэш обозревателя и переустановите приложение.

Если при проверке расширения отображается статус «Плагин загружен», но информации о криптопровайдере нет, то не установлен КриптоПро CSP. Загрузите ПО с ресурса разработчика и установите его на ПК. Если после этого не удастся начать работу с плагином, значит, адрес портала не включен в число разрешенных. Перейдите в настройки ПО и в графе «Список доверенных узлов» укажите адреса веб-сайта.

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

  1. Откройте «Пуск», выберите сначала «Все программы», далее «КриптоПро» и «Сертификаты».
  2. В открывшемся списке сначала выберите «Текущий Пользователь», «Личное» и затем «Сертификаты».
  3. В появившемся окне зайдите во вкладку «Путь сертификации». Если отображаются красные метки, то нужно загрузить и инсталлировать промежуточные и корневые сертификаты. Их скачивание происходит с ресурса удостоверяющего центра, где ранее получили документы. После установки перечисленных сертификатов будет создана цепочка доверия, и удастся завершить операцию.

Если при заверке документа система выдает ошибку x8007064A, значит, просрочен ключ у одного из продуктов КриптоПро — CSP, TSP Client 2.0 или OCSP Client 2.0. Для просмотра статуса лицензии перейдите в «Пуск», выберите «КриптоПро» и далее «Управление лицензиями». Найдите ПО с истекшим ключом. Приобретите лицензию повторно.

Подберем электронную подпись для вашего бизнеса за 5 минут!

Оставьте заявку и получите консультацию.

Оцените, насколько полезна была информация в статье?

Coogle chrome

Алгоритм действия для Chrome одинаков независимо от используемой версии ОС:

  1. Запустите интернет-обозреватель.
  2. Откроется окно с уведомлением об установке нового ПО. Нажмите на кнопку «Включить».
  3. Проверьте активацию  приложения. Для этого выберите в меню интернет-обозревателя сначала «Дополнительные инструменты», далее «Расширения».
  4. В перечне должно отобразиться название ранее установленного ПО.
  5. Если программного модуля нет, перейдите в интернет-магазин Chrome. Задайте в поисковой строке название плагина и нажмите «Найти». Откроется веб-страница с описанием ПО и опцией «Установить», активируйте ее. Дождитесь завершения процесса инсталляции и перезапустите интернет-обозреватель.

Вновь откройте браузер. Перейдите в раздел «Расширения» и найдите в перечне название приложения. Активируйте нажатием кнопки «Включить».

Mozilla firefox

Работа программного модуля в Mozilla Firefox поддерживается в версии обозревателя ниже 52. В более свежих версиях браузера использовать ЭЦП не получится. Для проведения настроек в Mozilla Firefox выполните следующие шаги:

  1. Запустите обозреватель. В открывшемся окне вверху справа кликните на иконку с тремя черточками для вызова главного меню. В списке выберите «Дополнения».
  2. Если в открывшемся перечне присутствует установленное ПО, то поставьте галочку напротив пункта «Всегда включать».
  3. Если в перечне отсутствует ранее установленное приложение, откройте в веб-обозревателе новую вкладку и укажите в поисковой строке запрос «config».
  4. На открывшейся странице выберите любой элемент и кликните правой кнопкой мыши. Откроется меню, где активируйте сначала «Создать», затем «Логическое».
  5. Откроется форма, где укажите следующий запрос: «plugin.load_flash_only».
  6. В списке «Значение» активируйте пункт «false».

Перезапустите интернет-обозреватель. Вновь перейдите в «Дополнения» и отметьте «Всегда включать» напротив названия программного модуля.

Opera

Для Opera алгоритм действий выглядит следующим образом:

  1. Откройте интернет-обозреватель.
  2. Выберите «Меню», где в выпадающем списке найдите «Расширения» и кликните двойным щелчком мыши.
  3. На открывшейся странице отобразятся все установленные плагины. Найдите в перечне нужное ПО и щелкните «Включить».
  4. Если в списке не окажется требуемого плагина, в разделе слева активируйте пункт «Добавить расширение». В поисковую строку введите название ПО и щелкните по найденному ярлыку.

На открывшейся странице активируйте опцию «Добавить в Опера».

Где и как приобрести электронную подпись

Квалифицированную электронную подпись могут выдавать только удостоверяющие центры, аккредитованные Минкомсвязи. УЦ «Астрал-М» предлагает электронные подписи с большим выбором тарифных планов и дополнительных услуг.

Для получения квалифицированной электронной подписи нужно проделать четыре простых шага:

  1. Оставьте заявку, заполнив форму обратной связи на странице «Астрал-ЭТ».
  2. Подготовьте необходимый пакет документов и отправьте на проверку специалистам УЦ «Астрал-М».
  3. Оплатите выставленный счёт.
  4. Получите готовую электронную подпись.

Специалисты УЦ «Астрал-М» помогут вам выбрать подходящий тариф и расскажут, какие документы вам понадобятся для выпуска электронной подписи.

Если вместо параметра метод

Иногда чтобы получить очередной параметр надо вызвать метод, например (родной код):

var signingTimeAttr = yield cadesplugin.CreateObjectAsync('CADESCOM.CPAttribute');
yield signingTimeAttr.propset_Name(0);
yield signingTimeAttr.propset_Value(timeNow);

С этой библиотекой будет выглядеть так

var attribute;
altCadesPlugin.get('CADESCOM.CPAttribute').then(function(attribute_){
    attribute = attribute_;
    altCadesPlugin.get(attribute, {method: 'propset_Name', args: [0]});
}).then(function(){
    altCadesPlugin.get(attribute, {method: 'propset_Value', args: [timeNow]});
});

Зависимости

Для корректной работы скрипта необходимы следующие библиотеки

  1. jquery
  2. es6-promise

Загрузить скрипт можно напрямую из репозитория или с помощью bower

В репозитории библитека находится в папке src

src/alt_cadesplugin_api.js

src/alt_cadesplugin_api.min.js

bower install cadesplugin

Запись данных (метод set)

Запишет значение 0 в параметр Name объекта CAdESCOM.CPAttribute

Если плагин работает без NPAPI то не надо заботиться о подставлении префикса propset_, это делается автоматически

altCadesPlugin.get('CAdESCOM.CPAttribute')
.then(function(attribute){
    altCadesPlugin.set(attribute, 'Name', 0);
});

Инструкция по настройке окружения для использования криптопро эцп browser plug-in

КриптоПро ЭЦП Browser plug-in предназначен для создания и проверки электронной подписи (ЭП) на веб-страницах с использованием СКЗИ “КриптоПро CSP”.

КриптоПро ЭЦП Browser plug-in применим в любом из современных браузеров с поддержкой сценариев JavaScript:

  • Google Chrome;
  • Opera;
  • Яндекс.Браузер;
  • Mozilla Firefox;
  • Apple Safari.

Поддерживаемые операционные системы:

  • Microsoft Windows;
  • Linux;
  • Apple iOS;
  • Apple MacOS.

Порядок установки и настройки:

Пройти проверку корректности настройки рабочего окружения

Использование

Для начала создаем экземпляр класса AltCadesPlugin

var altCadesPlugin;
altCadesPlugin = new AltCadesPlugin()

Как проверить браузер

Проверка «КриптоПро ЭЦП Browser plug-in» осуществляется на специальном сервисе разработчика «Cryptopro». Если расширение cadesplugin.exe установлено правильно, оно запросит доступ к сертификатам и ключам при переходе на сайт для проверки. Пользователю необходимо нажать «ОК». Далее появляется уведомление об успешном слиянии модуля, где указаны версия и криптопровайдер.

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

Как удалить плагин

Чтобы удалить «КриптоПро ЭЦП Browser plug-in» необходимо выполнить следующие действия:

  1. зайти в панель управления нажав кнопку меню «Пуск», далее «Параметры»;
  2. перейти в раздел управления программами в соответствии с версией Windows — «Установка и удаление программ» для Windows XP, «Программы и компоненты» для Windows Vista, Windows 7, Windows 8 или «Приложения» для Windows 10;
  3. в открывшемся окне выбрать программу «КриптоПро ЭЦП Browser Plug-in»;
  4. нажать «Удалить»;
  5. перезагрузить ПК.

Как установить и настроить криптопро эцп browser plug-in в разных браузерах

Установка «КриптоПро ЭЦП Browser plug-in» имеет различия в зависимости от браузера. На любой из браузеров нужно установить соответствующее расширение (дополнение).

Настройка криптопро эцп browser plug-in

  1. В браузереGoogle Chrome
    • Запустите Google Chrome. Ожидайте скрытой установки плагина.
    • По завершении установки плагина появится уведомление о том, что в браузер добавлено расширение или приложение: CryptoPro Extension for CAdES Browser Plug-in.
    • Нажмите кнопку “Включить расширение”.
    • Если расширение браузера не установилось, можете установить его вручную.
  1. В браузерах Яндекс.Браузер и браузер Opera
    • Перейдите по ссылке и установите расширение.
  2. В браузереFireFox
    • Перейдите по ссылке и установите расширение.
    • Нажмите кнопку “Добавить”.

Особенности некоторых браузеров по настройке работы плагина

  • в Mozilla Firefox 29 и выше: необходимо включить работу плагина (браузер может не запросить разрешения на включение плагина). Для этого пройти диагностику и выполнить фикс «Включение плагинов в Mozilla Firefox», после чего обязательно перезапустить Firefox. Также это можно сделать вручную: нажать Ctrl Shift A, перейти в раздел «Плагины», выбрать CryptoPro CAdES NPAPI Browser Plug-in и перевести его в состояние «Всегда включать» (Always active), после чего обязательно перезапустить Firefox.
  • в Google Chrome необходимо зайти по ссылке и установить расширение.
  • В Yandex Browser и Opera нужно установить расширение, доступное по этой ссылке
  • В Internet Explorer необходимо сделать следующие настройки:
Читайте также:  Как распечатать документ росреестр с цифровой подписью - Юрист в теме

Отличия от родной библиотеки

  1. Не запускает проверку плагина сразу при загрузке файла
  2. Использует jQuery.Deferred вместо нативных промисов
  3. Может подключаться к проекту как обычная библиотека, а также как amd/commonjs/node модуль

Подписание pdf на js и вставка подписи на c#, используя крипто про

Итак. Пришла задача. Используя браузер предложить пользователю подписать PDF электронной подписью (далее ЭП). У пользователя должен быть токен, содержащий сертификат, открытый и закрытый ключ. Далее на сервере надо вставить подпись в PDF документ. После этого надо проверить подпись на валидность. В качестве back-end используем ASP.NET и соответственно C#.

Вся соль в том, что надо использовать подпись в формате CAdES-X Long Type 1, и российские ГОСТ Р 34.10-2001, ГОСТ Р 34.10-2021 и т.п. Кроме того подписей может быть более одной, то есть пользователи могут по очереди подписывать файл. При этом предыдущие подписи должны оставаться валидными.

В процессе решения задачу решили усложнить для нас, и уменьшить объем передаваемых данных на клиент. Передавать только hash документа, но не сам документ.

В исходниках буду опускать малозначимые для темы моменты, оставлю только то что касается криптографии. Код на JS приведу только для нормальных браузеров, JS-движки которых поддерживают Promise и function generator. Думаю кому нужно для IE напишут сами (мне пришлось «через не хочу»).

Что нужно:

  1. Пользователь должен получить пару ключей и сертификат.
  2. Пользователь должен установить plug-in от Крипто ПРО. Без этого средствами JS мы не сможем работать с криптопровайдером.

Замечания:

  1. Для тестов у меня был сертификат выданный тестовым ЦС Крипто ПРО и нормальный токен, полученный одним из наших сотрудников (на момент написания статьи ~1500р с годовой лицензией на Крипто ПРО и двумя сертификатами: но «новому» и «старому» ГОСТ)
  2. Говорят, plug-in умеет работать и с ViPNet, но я не проверял.

Теперь будем считать что у нас на сервере есть готовый для подписывания PDF.

Добавляем на страницу скрипт от Крипто ПРО:

<script src="/Scripts/cadesplugin_api.js" type="text/javascript"></script>

Дальше нам надо дождаться пока будет сформирован объект cadesplugin

window.cadespluginLoaded = false;
cadesplugin.then(function () {
    window.cadespluginLoaded = true;
});

Запрашиваем у сервера hash. Предварительно для этого нам ещё надо знать каким сертификатом, а значит и алгоритмом пользователь будет подписывать. Маленькая ремарка: все функции и «переменные» для работы с криптографией на стороне клиента я объединил в объект CryptographyObject.

Метод заполнения поля certificates объекта CryptographyObject:

    fillCertificates: function (failCallback) {

            cadesplugin.async_spawn(function*() {
                try {
                    let oStore = yield cadesplugin.CreateObjectAsync("CAPICOM.Store");

                    oStore.Open(cadesplugin.CAPICOM_CURRENT_USER_STORE,
                        cadesplugin.CAPICOM_MY_STORE,
                        cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

                    let certs = yield oStore.Certificates;
                    certs = yield certs.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_TIME_VALID);
                    let certsCount = yield certs.Count;
                    for (let i = 1; i <= certsCount; i  ) {
                        let cert = yield certs.Item(i);
                        CryptographyObject.certificates.push(cert);
                    }
                    oStore.Close();
                } catch (exc) {
                     failCallback(exc);
                }
            });
    }

Комментарий: пробуем открыть хранилище сертификатов. В этот момент система пользователя выдаст предупреждение, что сайт пытается что-то сделать с сертификатами, криптографией и прочей магической непонятной ерундой. Пользователю тут надо будет нажать кнопку «Да»

Далее получаем сертификаты, валидные по времени (не просроченные) и складываем их в массив certificates. Это надо сделать из-за асинхронной природы cadesplugin (для IE всё иначе 😉 ).

Метод получения hash:

getHash: function (certIndex, successCallback, failCallback, какие-то ещё параметры) {
        try {
            cadesplugin.async_spawn(function*() {
                let cert = CryptographyObject.certificates[certIndex];
                let certPublicKey = yield cert.PublicKey();
                let certAlgorithm = yield certPublicKey.Algorithm;
                let algorithmValue = yield certAlgorithm.Value;
                let hashAlgorithm;
                //определяем алгоритм подписания по данным из сертификата и получаем алгоритм хеширования
                    if (algorithmValue === "1.2.643.7.1.1.1.1") {
                        hashAlgorithm = "2021256";
                    } else if (algorithmValue === "1.2.643.7.1.1.1.2") {
                        hashAlgorithm = "2021512";
                    } else if (algorithmValue === "1.2.643.2.2.19") {
                        hashAlgorithm = "3411";
                    } else {
                        failCallback("Реализуемый алгоритм не подходит для подписания документа.");
                        return;
                    }

                $.ajax({
                    url: "/Services/SignService.asmx/GetHash",
                    method: "POST",
                    contentType: "application/json; charset=utf-8 ",
                    dataType: "json",
                    data: JSON.stringify({
                        //какие-то данные для определения документа
                        //не забудем проверить на сервере имеет ли пользователь нужные права
                        hashAlgorithm: hashAlgorithm,
                    }),
                    complete: function (response) {
                        //получаем ответ от сервера, подписываем и отправляем подпись на сервер
                        if (response.status === 200) {
                            CryptographyObject.signHash(response.responseJSON,
                                function(data) {
                                    $.ajax({
                                        url: CryptographyObject.signServiceUrl,
                                        method: "POST",
                                        contentType: "application/json; charset=utf-8",
                                        dataType: "json",
                                        data: JSON.stringify({
                                            Signature: data.Signature,
                                            //какие-то данные для определения файла
                                            //не забудем про серверную валидацию и авторизацию
                                        }),
                                        complete: function(response) {
                                            if (response.status === 200)
                                                successCallback();
                                            else
                                                failCallback();
                                        }
                                    });
                                },
                                certIndex);
                        } else {
                            failCallback();
                        }
                    }
                });
            });
        } catch (exc) {
            failCallback(exc);
        }
    }

Комментарий: обратите внимание на cadesplugin.async_spawn, в нее передаётся функция-генератор, на которой последовательно вызывается next(), что приводит к переходу к yield.

Таким образом получается некий аналог async-await из C#. Всё выглядит синхронно, но работает асинхронно.

Теперь что происходит на сервере, когда у него запросили hash.

Во-первых необходимо установить nuget-пакет iTextSharp (на момент написания стать актуальная версия 5.5.13)

Во-вторых нужен CryptoPro.Sharpei, он идёт в нагрузку к Крипто ПРО .NET SDK

Теперь можно получать hash

                //определим hash-алгоритм
                HashAlgorithm hashAlgorithm;

                switch (hashAlgorithmName)
                {
                    case "3411":
                        hashAlgorithm = new Gost3411CryptoServiceProvider();
                        break;
                    case "2021256":
                        hashAlgorithm = new Gost3411_2021_256CryptoServiceProvider();
                        break;
                    case "2021512":
                        hashAlgorithm = new Gost3411_2021_512CryptoServiceProvider();
                        break;
                    default:
                        GetLogger().AddError("Неизвестный алгоритм хеширования", $"hashAlgorithmName: {hashAlgorithmName}");
                        return HttpStatusCode.BadRequest;
                }
                //получим hash в строковом представлении, понятном cadesplugin
                string hash;
                using (hashAlgorithm)
                //downloadResponse.RawBytes - просто массив байт исходного PDF файла
                using (PdfReader reader = new PdfReader(downloadResponse.RawBytes))
                {
                    //ищем уже существующие подписи
                    int existingSignaturesNumber = reader.AcroFields.GetSignatureNames().Count;
                    using (MemoryStream stream = new MemoryStream())
                    {
                        //добавляем пустой контейнер для новой подписи
                        using (PdfStamper st = PdfStamper.CreateSignature(reader, stream, '', null, true))
                        {
                            PdfSignatureAppearance appearance = st.SignatureAppearance;
                            //координаты надо менять в зависимости от существующего количества подписей, чтоб они не наложились друг на друга
                            appearance.SetVisibleSignature(new Rectangle(36, 100, 164, 150), reader.NumberOfPages,
                                //задаём имя поля, оно потом понадобиться для вставки подписи
                                $"{SignatureFieldNamePrefix}{existingSignaturesNumber   1}");
                            //сообщаем, что подпись придёт извне
                            ExternalBlankSignatureContainer external =
                                new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
                            //третий параметр - сколько места в байтах мы выделяем под подпись
                            //я выделяю много, т.к. CAdES-X Long Type 1 содержит все сертификаты по цепочке до самого корневого центра
                            MakeSignature.SignExternalContainer(appearance, external, 65536);
                            //получаем поток, который содержит последовательность, которую мы хотим подписывать
                            using (Stream contentStream = appearance.GetRangeStream())
                            {
                                //вычисляем hash и переводим его в строку, понятную cadesplugin
                                hash = string.Join(string.Empty,
                                    hashAlgorithm.ComputeHash(contentStream).Select(x => x.ToString("X2")));
                            }
                        }
                        //сохраняем stream куда хотим, он нам пригодиться, что бы вставить туда подпись
                    }
                }

На клиенте, получив hash от сервера подписываем его

    //certIndex - индекс в массиве сертификатов. На основании именно этого сертификата мы получали алгоритм и формировали hash на сервере
    signHash: function (data, callback, certIndex, failCallback) {
        try {
            cadesplugin.async_spawn(function*() {
                certIndex = certIndex | 0;

                let oSigner = yield cadesplugin.CreateObjectAsync("CAdESCOM.CPSigner");

                let cert = CryptographyObject.certificates[certIndex];

                oSigner.propset_Certificate(cert);
                oSigner.propset_Options(cadesplugin.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN);
                //тут надо указать нормальный адрес TSP сервера. Это тестовый от Крипто ПРО
                oSigner.propset_TSAAddress("https://www.cryptopro.ru/tsp/");

                let hashObject = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");

                let certPublicKey = yield cert.PublicKey();
                let certAlgorithm = yield certPublicKey.Algorithm;
                let algorithmValue = yield certAlgorithm.Value;

                if (algorithmValue === "1.2.643.7.1.1.1.1")  {
                    yield hashObject.propset_Algorithm(cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2021_256);
                    oSigner.propset_TSAAddress(CryptographyObject.tsaAddress2021);
                } else if (algorithmValue === "1.2.643.7.1.1.1.2") {
                    yield hashObject.propset_Algorithm(cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2021_512);
                    oSigner.propset_TSAAddress(CryptographyObject.tsaAddress2021);
                } else if (algorithmValue === "1.2.643.2.2.19") {
                    yield hashObject.propset_Algorithm(cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411);
                    oSigner.propset_TSAAddress(CryptographyObject.tsaAddress2001);
                } else {
                    alert("Невозможно подписать документ этим сертификатом");
                    return;
                }
                //в объект описания hash вставляем уже готовый hash с сервера
                yield hashObject.SetHashValue(data.Hash);

                let oSignedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
                oSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY);
                //результат подписания в base64
                let signatureHex =
                    yield oSignedData.SignHash(hashObject, oSigner, cadesplugin.CADESCOM_CADES_X_LONG_TYPE_1);

                data.Signature = signatureHex;
                callback(data);
            });
        } catch (exc) {
            failCallback(exc);
        }
    }

Комментарий: полученную подпись отправляем на сервер (см. выше)

Читайте также:  Новый стиль социальной карты москвича - Единый портал ЭП

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


//всякие нужные проверки
                //downloadResponse.RawBytes - ранее созданный PDF с пустым контейнером для подписи
                using (PdfReader reader = new PdfReader(downloadResponse.RawBytes))
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        //requestData.Signature - собственно подпись от клиента
                        IExternalSignatureContainer external = new SimpleExternalSignatureContainer(Convert.FromBase64String(requestData.Signature));
                    //lastSignatureName - имя контейнера, которое мы определили при формировании hash
                        MakeSignature.SignDeferred(reader, lastSignatureName, stream, external);
                        
                    //сохраняем подписанный файл
                    }
                }

Комментарий: SimpleExternalSignatureContainer — это простейший класс, реализующий интерфейс IExternalSignatureContainer

        /// <summary>
        /// Простая реализация контейнера внешней подписи
        /// </summary>
        private class SimpleExternalSignatureContainer : IExternalSignatureContainer
        {
            private readonly byte[] _signedBytes;

            public SimpleExternalSignatureContainer(byte[] signedBytes)
            {
                _signedBytes = signedBytes;
            }

            public byte[] Sign(Stream data)
            {
                return _signedBytes;
            }

            public void ModifySigningDictionary(PdfDictionary signDic)
            {

            }
        }

Собственно с подписанием PDF на этом всё. Проверка будет описана в продолжении статьи. Надеюсь, она будет…

Внёс исправления из комментария о получении Oid алгоритма подписи. Спасибо

Подписывание данных (метод signdata)

altCadesPlugin.getCertificates()
.then(function(certificates){
    certificate = certificates[0].certificate;
    altCadesPlugin.signData('Hello World!', certificate);
}).then(function(signature){
    alert(signature);
});

Подпись файла с использованием fileapi и чтением файла по частям

Пример создания и проверки подписи файла с использованием FileAPI и чтением файла по частям

Приведенный пример использует синхронную версию плагина. Также см. пример работы с асинхронными обьектами.

JavaScript

        var CADESCOM_CADES_BES = 1;
        var CAPICOM_CURRENT_USER_STORE = 2;
        var CAPICOM_MY_STORE = "My";
        var CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED = 2;
        var CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME = 1;
        var CADESCOM_BASE64_TO_BINARY = 1;

        function signCreate(certSubjectName, oHashedData) {
            var oStore = cadesplugin.CreateObject("CAdESCOM.Store");
            oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE,
                CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

            var oCertificates = oStore.Certificates.Find(
                CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, certSubjectName);
            if (oCertificates.Count == 0) {
                alert("Certificate not found: "   certSubjectName);
                return;
            }
            var oCertificate = oCertificates.Item(1);
            var oSigner = cadesplugin.CreateObject("CAdESCOM.CPSigner");
            oSigner.Certificate = oCertificate;

            var oSignedData = cadesplugin.CreateObject("CAdESCOM.CadesSignedData");
            oSignedData.ContentEncoding = CADESCOM_BASE64_TO_BINARY;

            try {
                var sSignedMessage = oSignedData.SignHash(oHashedData, oSigner, CADESCOM_CADES_BES);
            } catch (err) {
                alert("Failed to create signature. Error: "   cadesplugin.getLastError(err));
                return;
            }

            oStore.Close();

            return sSignedMessage;
        }

        function Verify(sSignedMessage, oHashedData) {
            var oSignedData = cadesplugin.CreateObject("CAdESCOM.CadesSignedData");
            try {
                oSignedData.VerifyHash(oHashedData, sSignedMessage, CADESCOM_CADES_BES);
            } catch (err) {
                alert("Failed to verify signature. Error: "   cadesplugin.getLastError(err));
                return false;
            }

            return true;
        }

        function signFile(file, certSubjectName) {
            var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
            var chunkSize = 3 * 1024 * 1024; // 3MB
            var chunks = Math.ceil(file.size / chunkSize);
            var currentChunk = 0;

            var oHashedData = cadesplugin.CreateObject("CAdESCOM.HashedData");
            oHashedData.DataEncoding = CADESCOM_BASE64_TO_BINARY;

            var progress = document.getElementById("progressbar").childNodes.item(1);

            var frOnload = function(e) {
                var header = ";base64,";
                var sFileData = e.target.result;
                var sBase64Data = sFileData.substr(sFileData.indexOf(header)   header.length);

                oHashedData.Hash(sBase64Data);

                var percentLoaded = Math.round((currentChunk / chunks) * 100);
                // Increase the progress bar length.
                if (percentLoaded <= 100) {
                    progress.style.width = percentLoaded   '%';
                    progress.textContent = percentLoaded   '%';
                }

                currentChunk  ;

                if (currentChunk < chunks) {
                    loadNext();
                }
                else {
                    document.getElementById("progressbar").style.visibility = "hidden";
                    var signedMessage = signCreate(certSubjectName, oHashedData);
                    // Выводим отделенную подпись в BASE64 на страницу
                    // Такая подпись должна проверяться в КриптоАРМ и cryptcp.exe
                    document.getElementById("signature").innerHTML = signedMessage;

                    // Проверим подпись
                    var verifyResult = Verify(signedMessage, oHashedData);
                    if (verifyResult) {
                        alert("Signature verified");
                    }
                }
            };

            var frOnerror = function() {
                alert("File load error.");
            };

            function loadNext() {
                var fileReader = new FileReader();
                fileReader.onload = frOnload;
                fileReader.onerror = frOnerror;

                var start = currentChunk * chunkSize,
                end = ((start   chunkSize) >= file.size) ? file.size : start   chunkSize;

                fileReader.readAsDataURL(blobSlice.call(file, start, end));
            };

            loadNext();
        }

        function doCheck() {
            // Проверяем, работает ли File API
            if (window.FileReader) {
                // Браузер поддерживает File API.
            } else {
                alert("The File APIs are not fully supported in this browser.");
            }
            var fileReader = new FileReader();
            if (typeof(fileReader.readAsDataURL)!="function") {
                alert("Method readAsDataURL() is not supported in FileReader.");
                return;
            }
        }

        function doSign() {
            // Проверяем, работает ли File API
            doCheck();
            if (1 != document.getElementById("uploadFile").files.length) {
                alert("Select the file.");
                return;
            }

            var oFile = document.getElementById("uploadFile").files[0];

            var oCertName = document.getElementById("CertName");
            var sCertName = oCertName.value; // Здесь следует заполнить SubjectName сертификата
            if ("" == sCertName) {
                alert("Введите имя сертификата (CN).");
                return;
            }
            signFile(oFile, sCertName);
        }

Получение версии криптопро csp (метод getcspversion)

altCadesPlugin.getCSPVersion()
.then(function(version){
    version.major; // 4
    version.minor; // 0
    version.build; // 9630
    version.full; // 4.0.9630
});

Получение версии плагина (метод getversion)

altCadesPlugin.getVersion()
.then(function(version){
    version.major; // 2
    version.minor; // 0
    version.build; // 12245
    version.full; // 2.0.12245
});

Получение данных (метод get)

altCadesPlugin.get('CAdESCOM.About').then(function(aboutObject){
    В этом колбэке доступна переменная aboutObject, в которой хранится только что созданный объект
});

Получение списка сертификатов (метод getcertificates)

altCadesPlugin.getCertificates()
.then(function(certificates){
    certificates.subject; // владелец сертификата
    certificates.issuer; // издатель сертификата
    certificates.validFrom; // дата начала действия сертификата, дата выдачи
    certificates.validTo; // дата окночания действия сертификата
    certificates.algorithm; // алгоритм шифрования
    certificates.hasPrivateKey; // наличие закрытого ключа
    certificates.isValid; // валидность
    certificates.thumbprint; // слепок, хэш
    certificates.certificate; // объект сертификата
});

Получение цепочки данных (метод get)

altCadesPlugin.get('CAdESCOM.About', 'PluginVersion', 'MajorVersion').then(function(majorVersion){
    В этом колбэке доступна переменная majorVersion, в которой хранится major-версия плагина
});

При использовании нативной библиотеки код выглядел бы так:

var about = yield cadesplugin.CreateObjectAsync('CAdESCOM.About');
var pluginVersion = yield about.PluginVersion;
var majorVersion = yield pluginVersion.MajorVersion;

Пример проверяющего наличие расширения кода

Чтобы активировать объекты расширения Browser plug-in, необходимо подключить файл cadesplugin_api.js к странице.

Через HTML это можно сделать так:

Через JavaScript делают так:// Создание объектаcryptopro ЭЦП Browser plug-in varoStore =cadesplugin.CreateObject(«CAdESCOM.Store»); varoSigner =cadesplugin.CreateObject(«CAdESCOM.CPSigner»); var oPrivateKey =cadesplugin.CreateObject(«X509Enrollment.CX509PrivateKey»).

Согласно новому ГОСТу все владельцы ЭЦП обязаны использовать последнюю версию плагина, отвечающую требованиям безопасности ФСБ. Загрузка расширения на ОС Windows проходит в автоматическом режиме, а последующая настройка зависит от используемого браузера.

Работа с расширением в системах Unix требует скачивания и распаковки архивов, подходящих под битность ОС. Последующая настройка схожа с ОС Windows. Перед началом работы с плагином необходимо через демо-страницу ввести данные пользователя и сертификата ЭЦП.

Проверка криптопро эцп browser plug-in

  1. Перейдите по ссылке, чтобы проверить работу плагина.
  2. Должна открыться страница со всплывающим окном “Подтверждение доступа”.
  3. Нажмите кнопку “Да”, чтобы разрешить плагину операцию с ключами и сертификатами от имени пользователя. Предоставление разрешения позволит плагину найти сертификаты, установленные на устройстве или внешних носителях.
  1. Если плагин КриптоПро ЭЦП Browser plug-in установлен корректно, то вы увидите следующую информацию: “Плагин загружен”. Также будет отображаться версия плагина, название и версия криптопровайдера.

Установили КриптоПро ЭЦП Browser plug-in или, наоборот, столкнулись с проблемами?

Напишите о своем опыте в комментариях! Мы будем рады обратной связи.

Читайте также:  Получаем ЭЦП для участия в электронных торгах 2019

Проверка подписи криптопро

Чтобы проверить ЭЦП, необходимо воспользоваться специальным сервисом компании «КриптоПро»:

  1. Перейти на сервис КриптоПро DSS.
  2. Нажать «Выбрать» и указать путь к нужному документу.
  3. Указать «Проверка требований к квалифицированному сертификату», если того требует формат подписи.
  4. Система обработает документ представит результат проверки ЭЦП КриптоПро.

Представленный для проверки сервис бесплатный и не требует предварительной регистрации ЭЦП.

Процесс настройки

Дальнейшая настройка браузера зависит от используемой программы. Для IE дополнительные настройки не требуются, и сразу после установки и перезагрузки можно оценить корректность работы плагина. Для этого нужно в открывшейся форме разрешить операцию:

Если ошибок нет и установка прошла успешно, то система выдаст сообщение:

Проверка корректности работы плагина обязательна, т.к. без нее невозможно оценить готовность плагина к формированию ЭЦП.

Системные требования

  • Установка плагина возможна на следующих операционных системах:  Win XP SP3, Win Vista SP2, Win 2003 SP2, Win 2008 SP2, Win 7, Win 2008 R2, Win 8, Win8.1, Win10.
  • Работает с браузерами: IE 8 — 11, Opera, Mozilla Firefox, Google Chrome, Yandex Browser

           Не работает в браузере EDGE, предустановленном по умолчанию в Windows 10.

  • Требуется предустановленная КриптоПро CSP версии не ниже 3.6 R2

Следующим шагом инициализировать

altCadesPlugin.nonNpapiInit()
.then(function(){
    Следующий код уже будет в колбэках промисов
    ...
});

Установка и настройка крипто про эцп браузер плагин

ПО CryptoPro корректно работает с большинством интернет-обозревателей, поддерживающих выполнение сценариев на языке JavaScript. В их числе:

  • Opera;
  • Yandex;
  • Internet Explorer;
  • Mozilla Firefox;
  • Chrome.

Перед установкой приложения убедитесь в том, в  операционной системе для вас включены права администратора, а все приложения и документы закрыты. Далее действуйте согласно следующей инструкции:

  1. Найдите скачанный дистрибутив CadesPlugIn.exe — по умолчанию сохраняется в папку «Загрузки».
  2. Щелкните два раза по файлу.
  3. В окне активируйте опцию «Запустить».
  4. Подтвердите намерение установки ПО путем нажатия на кнопку «Да».
  5. Запустится инсталляция вспомогательных компонентов. По завершении процесса кликните «ОК» и перезапустите операционную систему.

Процесс настройки  Крипто Про ЭЦП Браузер плагин зависит от используемого интернет-обозревателя.

Установка плагина на unix

Работа с ЭЦП в системе Unix возможна с браузерами Firefox, Opera версии 35, Chromium, Chrome, а также Яндекс.

Электронная цифровая подпись на сайте при помощи криптопро эцп browser plug-in

В данной статье рассмотрим использование электронно-цифровой подписи на сайте.

Что необходимо, чтобы человек смог использовать электронно-цифровую подпись на сайте?

1) СКЗИ (средство криптографической защиты информации)
Мой опыт работы показывает, что порядка 90% использует КриптоПро CSP (скачать), который в явном или неявном виде продвигают удостоверяющие центры. Порядка 10% VipNet CSP (), который можно использовать бесплатно. С остальными СКЗИ на практике не встречался.
2) КриптоПро ЭЦП Browser plug-in (страница плагина).
3) Установленная подпись (хотя бы одна).

Проверка возможности осуществления подписи
javascript ( jquery)

1) Попытка создать объект cades.
Нужно сделать примечание, что тут и далее, будет деление на браузер с ActiveX(читай IE) и остальные.
Проверка будет осуществляться:

return ('ActiveXObject' in window);

для ActiveX:

try {
    store = new ActiveXObject('CAdESCOM.store');
    status = true;
} catch (e) {
    status = false;
}

Для остальных:

if (navigator.mimeTypes['application/x-cades']) {
    status = true;
} else {
    status = false;
}

Если проверка прошла неудачно, то уведомляем об этом пользователя.

Стоит иметь ввиду, что после обновления хрома до версии 42 (спасибо

статье

за информацию) нужно включить:

chrome://flags/#enable-npapi

Следующая проверка — а разрешен ли плагин для запуска (не для IE проверка)?

try {
    store = objSign.CreateObject('CAPICOM.store');
    status = true;
} catch (e) {
    status = false;
}

Где objSign:

objSign = $('<object/>', {
    'id': 'cadesplugin',
    'type': 'application/x-cades',
    'css': {
        'visibility': 'hidden',
        'height': '0px',
        'width': '0px',
        'position': 'absolute'
    }
}).appendTo('body').get(0);

Проверяем на СКЗИ путем попытки открыть хранилище.

try {
    store.Open();
    status = true;
} catch (e) {
    status = false;
}

Проверяем на существование сертификатов в хранилище:

if ('Certificates' in store) {
    certs = store.Certificates;
}

И их количество (бывает, что Certificates есть, но пуст, что нам тоже не подойдет):

if (certs.Count) {
    status = true;
} else {
    status = false;
}

Первый шаг сделали — проверили возможность подписания чего-либо.

Выбор электронной цифровой подписи

У клиента может быть установлено несколько сертификатов. Сертификаты могут быть от разных удостоверяющих центров (УЦ), выданными быть разным людям, с разными датами выдачами, поэтому надо предоставить выбор, каким именно он хочется воспользоваться.

1) Группируем по удостоверяющим центрам
Информация об удостоверяющем центре хранится в сертификате.

certs.Item(i).GetInfo(1)
где certs — сертификаты из хранилища, см выше
i — порядковый номер сертификата от 1 (обратите внимание) до certs.Count.
Обратите внимание, что, в случае «кривых» сертификатов, вернуться может и undefined, имеет смысл сделать один дефолтный УЦ для таких случаев.

Теперь мы знаем список УЦ, услугами которых воспользовался клиент.
Запоминаем их и выведем через optgroup.
Сам text у option будет таким:

cert.GetInfo(6)   ' ('   formatDate(cert.ValidFromDate)   ' - '   formatDate(cert.ValidToDate)   ')'

в

cert.GetInfo(6)

— кому выдан сертификат

в

ValidFromDate

— с какого срока сертификат начал/начнет действие

в

ValidToDate

— соответственно, до какого срока

Ну и форматирование даты стандартное:

function formatDate(d) {
    try {
        d = new Date(d);
        return ('0'   d.getDate()).slice(-2)   '.'   ('0'   (d.getMonth()   1)).slice(-2)   '.'   d.getFullYear();
    } catch (e) {
        return '';
    }
}

Еще можно подсветить option.

Зеленым — для работоспособных сертификатов, красным — нет.

Информацию можно получить при помощи самого сертификата.

try {
    return cert.IsValid().Result;
} catch (e) {
    return false;
}

Стоит отметить, что сама по себе данная проверка имеет малую ценность, ибо все причины не может отсечь.

Но самые базовые, например, проверка даты — проверяет.

В value у option запишем отпечаток cert.Thumbprint.
Можно порядковый номер записать, можно другие данные — на ваше усмотрение.

Подписание
Ну и, собственно, самый главный шаг, к которому мы стремились — подписание.

1) Находим выбранный сертификат.
Для нашего примера:

certs.Find(0, thumbprint).Item(1)

— означает, что мы ищем по отпечатку

1

— что используем первый результат выборки (по факту единственный)

2) Подписываем:

if (isActiveX()) {
    var CPSigner = new ActiveXObject('CAdESCOM.CPSigner');
} else {
    var CPSigner = objSign.CreateObject('CAdESCOM.CPSigner');
}
CPSigner.Certificate = cert;
if (isActiveX()) {
    var SignedData = new ActiveXObject('CAdESCOM.CadesSignedData');
} else {
    var SignedData = objSign.CreateObject('CAdESCOM.CadesSignedData');
}
SignedData.Content = text;
return SignedData.SignCades(CPSigner, 1, false);

где cert — сертификат, при помощи которого подписываем
text — собственно, что подписываем
Ну а в return возвращается подписанное сообщение.

p.s. По максимуму код постарался вычистить от специфики проекта. Если кому-то этот материал пригодится и будет интересно — напишу и серверную часть. Проверка подписанного сообщения (с цепочкой и без), проверка сертификата (ocsp и без), использования tsp и т.д.

Яндекс.браузер

Настройка в Яндекс.Браузере проходит наиболее быстро. Выполните следующие шаги:

  1. Запустите интернет-обозреватель.
  2. Кликните по иконке с тремя черточками — находится вверху справа.
  3. В меню щелкните по строке «Дополнения».

Откроется страница, которую нужно прокрутить в самый низ. Напротив ранее инсталлированного ПО нажмите «Включить».

Вам будет интересно: Плагин ЭЦП от КриптоПро: обзор, установка

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector