@Sell_Your_Soul

Как реализовать функционал подписи документа с помощью CryptoPro на Laravel?

Имеется сайт на Laravel-10 (используем node.js + webpack, jQuery в основе клиентского функционала).
Сервер - VPS, nginx, сборка LEMP, хостится в REG.RU. БД mysql.

Стоит задача создать на сайте функционал подписи PDF-файлов усиленной квалифицированной электронной подписью (ЭЦП) на стороне клиента.
Фактически это должно работать примерно так:
-На сайте генерируется PDF-файл (на основе данных пользователя)
-Пользователю предлагается подписать данный документ ЭЦП
-Пользователь осуществляет подпись
-Если документ успешно подписан, он сохраняется на сервер, а пользователь получает уведомление

Потенциально планирую использовать:
-CryptoPro Browser Plug-in
-(возможно какие-либо ещё инструменты/решения CryptoPRO)

К сожалению, не смог найти внятной документации, кроме того, вообще нет опыта работы с браузерными плагинами (строго говоря, не особо представляю даже обмен информацией между ними). Если кто-то делал что-то подобное или хотя бы может подсказать, куда копать, буду рад помощи, спасибо!

P.S. Документация есть в таком виде, честно, даже не уверен, что это именно то решение: https://docs.cryptopro.ru/cades/plugin/plugin-usage
  • Вопрос задан
  • 413 просмотров
Пригласить эксперта
Ответы на вопрос 2
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Установите утилиты для работы с подписью из командной строки - "cryptcp"
Сделайте на PHP обвязку поверх них с запуском через exec/passthru
Ответ написан
Комментировать
@vlog
Недавно реализовывал этот функционал, подписывал файлы, которые уже загружены на сервер. Сама подпись может быть реализована только на фронте и по-сути это вопрос фронта, кроме CryptoPro Browser Plug-in ничего особо не нужно, но я для удобства использовал эту библиотеку.

С помощью этих функций реализовал создание подписи:

import {
    createAttachedSignature,
    createDetachedSignature,
    createHash,
    createXMLSignature,
    getSystemInfo,
    getUserCertificates
} from "crypto-pro";

// В this.cert.thumbprint лежит выбранный пользователем thumbprint

sign(url){

            if(!this.cert.thumbprint){
                alert('Подпись не выбрана. Выберите подпись.');
                return;
            }
           
            this.signFile = section;

            let self = this;

            // В моём случае пользователь не загружал файлы для подписания, а подписывал уже имевшиеся на сервере, поэтому в эту функцию передаётся ссылка на файл, функция получает его, обрабатывает и подписывает
            fetch(url)
                .then(res => res.blob()) // Gets the response and returns it as a blob
                .then(blob => {
                    // Here's where you get access to the blob
                    // And you can use it for whatever you want
                    // Like calling ref().put(blob)
              
                    var oFReader = new FileReader();
                    oFReader.readAsArrayBuffer(blob);

                    // javascript имеет событийную модель, когда процесс чтения завершиться продолжаем исполнять сценарий
                    oFReader.onload = function(oFREvent) {
                        let sBase64Data = this.result;
                        createHash(sBase64Data).then(self.createSignature.bind(null, sBase64Data), function (hashError) {
                            //
                        });

                    };
                });

        },
          createSignature(message, hash){
            let self = this;

            var thumbprint = this.cert.thumbprint,
                signatureType = 'detached',
                signaturePromise;

            switch (signatureType) {
                case 'attached':
                    signaturePromise = createAttachedSignature(thumbprint, message);
                    break;
                case 'xml':
                    signaturePromise = createXMLSignature(thumbprint, message);
                    break;
                case 'detached':
                    signaturePromise = createDetachedSignature(thumbprint, hash);
                    break;
            }
            
            signaturePromise.then(function (signature) {
                axios.post(route('addSign'), {
                    fileSectionId: self.signFile,
                    signature: signature, // Тут отправлял текст подписи и уже на сервере сохранял её в файл .sign
                    certInfo: self.cert,
                })
                    .then(function (data){
                        alert('Создание подписи завершилось успехом');
                    });
            }, function (error) {
                alert('Создание подписи завершилось с ошибкой. Подпись не создана.');
            });
        },


Когда всё сделаете, обязательно проверьте действительность подписи на госуслугах, чтобы понять, что всё работает корректно.
Остальное по формированию PDF и сохранению на сервере найдёте сами.

PS Не бойтесь пользоваться Интернетом :)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы