Типичная ситуация: вы заключаете договор с контрагентом через электронный документооборот, но он сомневается в подлинности подписи. Или вам нужно предоставить клиентам возможность проверить подписанный документ онлайн. Мы решаем эту задачу: от интеграции простой ЭП до криптографической верификации КЭП через КриптоПро.
Какие проблемы решает система верификации?
Разные типы подписей — разная логика проверки. Простая электронная подпись (рисованная подпись, SMS-код) не несёт криптографической защиты. Единственный способ проверить её подлинность — убедиться, что документ не изменялся после подписания. Для этого мы храним хэш документа (SHA-256) в момент подписания и сравниваем его при верификации. Если хэши не совпадают — документ был изменён, подпись недействительна.
Квалифицированная электронная подпись (КЭП) требует гораздо более сложной проверки. Нужно расшифровать подпись, проверить сертификат, цепочку доверия, срок действия, статус отзыва. Это включает работу с криптопровайдерами (КриптоПро), плагинами браузера или серверными SOAP-вызовами.
Совместимость с браузерами и устройствами. Клиентская верификация КЭП требует установки Browser Plugin, что не всегда возможно (мобильные устройства, корпоративные ограничения). Поэтому мы предлагаем серверную верификацию через КриптоПро Web Service — пользователь просто загружает документ и подпись, а вся криптография выполняется на сервере. Это универсальное решение.
Безопасность и логирование. Важно не только проверить подпись, но и сохранить доказательства проверки. Мы логируем каждую попытку: IP, User-Agent, временную метку, результат. Это защищает от атак повторного воспроизведения и даёт аудиторский след.
Как мы это делаем?
Архитектура решения
- Frontend: React 18 (Next.js 14) для публичной страницы верификации, TypeScript, Tailwind.
- Backend: Laravel 11 (PHP 8.3) или Node.js (Express) для API и серверной верификации.
- База данных: PostgreSQL для хранения хэшей и логов, Redis для кэширования статусов сертификатов.
- Криптография: КриптоПро CSP (серверная верификация через SOAP) и CryptoPro Browser Plugin (клиентская).
Код клиентской верификации КЭП через плагин уже готов и используется в проектах:
async function verifyCadesSignature(documentBase64, signatureBase64) { const plugin = await cadesplugin; const signedData = await plugin.CreateObjectAsync('CAdESCOM.CadesSignedData'); await signedData.propset_ContentEncoding(plugin.CADESCOM_BASE64_TO_BINARY); await signedData.propset_Content(documentBase64); try { await signedData.VerifyCades( signatureBase64, plugin.CADESCOM_CADES_BES, true ); } catch (e) { return { valid: false, error: e.message }; } const signers = await signedData.Signers; const signer = await signers.Item(1); const cert = await signer.Certificate; return { valid: true, signer: { name: await cert.GetInfo(plugin.CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME), issuer: await cert.GetInfo(plugin.CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME), validFrom: await cert.ValidFromDate, validTo: await cert.ValidToDate, thumbprint: await cert.Thumbprint, }, signedAt: await signer.SigningTime, certValid: await cert.IsValid().Result, }; } Серверная верификация через КриптоПро Web Service — пример на PHP:
class CryptoProVerificationService { public function verifySignature(string $documentBase64, string $signatureBase64): array { $client = new SoapClient('https://www.cryptopro.ru/ocsp/ocsp.php?wsdl'); $result = $client->VerifyHash([ 'Signature' => $signatureBase64, 'Content' => $documentBase64, 'Type' => 'CAdES-BES', 'IsDetached' => true, ]); return [ 'valid' => $result->IsValid, 'signerName' => $result->SignerName, 'signedAt' => $result->SigningTime, 'certSerial' => $result->CertSerialNumber, ]; } } Почему серверная верификация лучше для пользователя?
Серверная верификация не требует установки плагинов, работает на любых устройствах и браузерах. Проверка занимает 2-3 секунды — в 2 раза быстрее, чем установка и настройка плагина. Это снижает количество обращений в поддержку и повышает конверсию верификации.
Как публичная страница и QR-код упрощают проверку?
Для внешних пользователей (контрагент проверяет договор) мы создаём страницу без авторизации. Пример компонента на React:
async function VerificationPage({ params }) { const result = await verifyDocumentSignature(params.documentId, params.signatureId); return ( <div className="max-w-2xl mx-auto p-8"> <div className={`rounded-xl p-6 ${result.valid ? 'bg-green-50' : 'bg-red-50'}`}> <div className="flex items-center gap-3"> {result.valid ? <CheckCircleIcon className="text-green-600 w-8" /> : <XCircleIcon className="text-red-600 w-8" />} <h1 className="text-xl font-bold"> {result.valid ? 'Подпись действительна' : 'Подпись недействительна'} </h1> </div> {result.valid && ( <dl className="mt-4 grid grid-cols-2 gap-4 text-sm"> <div><dt className="text-gray-500">Подписант</dt><dd>{result.signerName}</dd></div> <div><dt className="text-gray-500">Дата подписания</dt><dd>{formatDate(result.signedAt)}</dd></div> <div><dt className="text-gray-500">Документ не изменён</dt><dd>Да</dd></div> <div><dt className="text-gray-500">Сертификат</dt><dd>{result.certSerial}</dd></div> </dl> )} </div> </div> ); } QR-код, размещённый на подписанном документе, ведёт на страницу верификации:
import QRCode from 'qrcode'; const verificationUrl = `${process.env.APP_URL}/verify/${documentId}/${signatureId}`; const qrDataUrl = await QRCode.toDataURL(verificationUrl, { width: 100, margin: 1, errorCorrectionLevel: 'M', }); Сравнение методов верификации
| Метод | Скорость проверки | Требования к клиенту | Безопасность | Тип подписи |
|---|---|---|---|---|
| По хэшу документа | Мгновенно | Любой браузер | Средняя (защита от изменений) | Простая ЭП |
| КЭП через плагин | ~1 сек | Установка CryptoPro Browser Plugin | Высокая (криптография) | КЭП |
| КЭП серверная | ~2-3 сек | Нет (SOAP на сервере) | Высокая (криптография) | КЭП |
Процесс работы
- Аналитика — выявляем типы подписей, требования к безопасности, поток пользователей.
- Проектирование — выбираем архитектуру (клиентская/серверная верификация), стек, протоколы.
- Разработка — реализуем API, публичную страницу, QR-код, интеграцию с вашей CRM/ERP.
- Тестирование — проверяем на разных браузерах, с реальными сертификатами, нагрузочное тестирование.
- Деплой — настраиваем CI/CD, мониторинг, кэширование.
- Обучение и поддержка — передаём документацию, доступы, проводим обучение сотрудников. Предоставляем 1 месяц бесплатной поддержки.
Что входит в работу
- Исходный код системы верификации.
- Документация API (OpenAPI/Swagger).
- Инструкция по эксплуатации для администраторов.
- Доступы к репозиторию и серверу.
- 1 месяц поддержки после запуска.
Типичные ошибки при внедрении
- Не проверяется срок действия сертификата — подпись может быть создана просроченным сертификатом. Мы всегда проверяем ValidFrom/ValidTo.
- Отсутствует логирование попыток верификации — сложно доказать, что проверка была выполнена. Мы логируем каждую попытку.
- QR-код ведёт на HTTP, а не HTTPS — данные подписи передаются в открытом виде. Мы используем только HTTPS с HSTS.
- Не настроен CORS — публичная страница не загружается из-за ограничений браузера. Мы правильно конфигурируем заголовки.
Сроки
Верификация по хэшу с публичной страницей и QR-кодом — 2–3 дня. Верификация КЭП через браузерный плагин — 3–4 дня. Серверная верификация через КриптоПро Web Service — 3–5 дней. Точную оценку дадим после аудита вашего проекта.
Свяжитесь с нами, чтобы обсудить детали. Закажите разработку системы верификации подписи — оценим проект в течение одного рабочего дня.







