Реализация электронного подписания документов
Недавно к нам обратился fintech-стартап: их система подписания договоров с клиентами состояла из простого SMS-кода без соглашения об ЭП. После аудита выяснилось, что юридическая сила таких подписей — ноль, а все договоры под угрозой ничтожности. Мы оперативно внедрили полный цикл: от SMS-кода до КЭП через СБИС. Рассказываем, как избежать подобных ошибок и реализовать юридически значимую электронную подпись на сайте.
Различают три типа ЭП: простая (ПЭП — логин/пароль/SMS-код), усиленная неквалифицированная (НЭП — криптография, сертификат ключа проверки), квалифицированная (КЭП — только через удостоверяющий центр, приравнивается к собственноручной). Выбор зависит от требований к юридической значимости и бюджета. Сравним их ключевые характеристики:
| Тип ЭП | Юридическая сила | Сложность реализации | Стоимость | Срок внедрения |
|---|---|---|---|---|
| ПЭП | Требует соглашения | Низкая | Низкая | 1–2 дня |
| НЭП | Средняя (с сертификатом) | Средняя | Средняя | 3–5 дней |
| КЭП | Высшая (равна собственноручной) | Высокая | Высокая | 5–10 дней |
Почему простая ЭП без соглашения — это ловушка?
Без отдельного соглашения об использовании простой ЭП (оферты или договора присоединения) подпись не имеет юридической силы. Согласно 63-ФЗ, простая ЭП признаётся равнозначной собственноручной подписи только при наличии соглашения между сторонами. Мы всегда фиксируем факт акцепта соглашения через отдельный чекбокс и храним аудит-лог. Иначе даже при успешном SMS-подтверждении документ можно оспорить в суде.
Когда без квалифицированной подписи не обойтись?
КЭП обязательна для госзакупок (44-ФЗ, 223-ФЗ), отчётности в ФНС, Росреестр и сделок с недвижимостью. Юридическая сила КЭП в сотни раз выше, чем у простой ЭП — она подтверждается сертификатом УЦ и ключом ФСБ. Ошибка при выборе может привести к штрафам до 500 000 рублей и признанию сделок недействительными.
Как работает простая ЭП: SMS-подписание договора
Наиболее распространённый подход для B2C: пользователь получает код по SMS, вводит его, мы фиксируем отметку времени, IP, fingerprint и хэш документа. Юридически значима как простая ЭП только при наличии отдельного соглашения об использовании ЭП. Без него — просто подтверждение действия.
// Модель документа с аудитом подписания class Document extends Model { protected $casts = [ 'signing_metadata' => 'array', 'signed_at' => 'datetime', ]; } // Сервис подписания class DocumentSigningService { public function initiateSignin(Document $document, User $user): void { // Генерация и отправка кода $code = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT); Cache::put("signing_code:{$document->id}:{$user->id}", bcrypt($code), now()->addMinutes(15)); $user->notify(new DocumentSigningCodeNotification($code, $document)); } public function confirmSigning(Document $document, User $user, string $code, Request $request): void { $cached = Cache::get("signing_code:{$document->id}:{$user->id}"); if (!$cached || !Hash::check($code, $cached)) { throw new InvalidSigningCodeException('Неверный или истёкший код подтверждения'); } // Создать хэш текущей версии документа $documentHash = hash('sha256', Storage::disk('s3')->get($document->path)); $document->update([ 'status' => 'signed', 'signed_at' => now(), 'signed_by' => $user->id, 'document_hash' => $documentHash, 'signing_metadata' => [ 'ip' => $request->ip(), 'user_agent' => $request->userAgent(), 'fingerprint' => $request->header('X-Client-Fingerprint'), 'method' => 'sms_code', 'phone_last4' => substr($user->phone, -4), 'code_sent_at' => Cache::get("signing_code_sent_at:{$document->id}:{$user->id}"), 'signed_at_iso' => now()->toIso8601String(), 'timezone' => $request->header('X-Timezone', 'UTC'), ], ]); // Зафиксировать подпись в аудит-логе AuditLog::create([ 'action' => 'document.signed', 'user_id' => $user->id, 'document_id' => $document->id, 'metadata' => $document->signing_metadata, ]); Cache::forget("signing_code:{$document->id}:{$user->id}"); // Отправить подписанную копию на email $user->notify(new DocumentSignedNotification($document)); } } Как встроить визуальную подпись в PDF и не потерять юридическую силу?
Для интерфейсов, где пользователь рисует подпись стилусом или мышью, подключаем библиотеку react-signature-canvas (Canvas API). Важно: сама по себе растровая подпись не имеет юридической силы — её нужно привязать к документу через хэш и метаданные. Мы используем два шага: сначала сохраняем изображение подписи и инициируем сессию, затем подтверждаем SMS-кодом.
import SignatureCanvas from 'react-signature-canvas'; import { useRef, useState } from 'react'; function DocumentSigner({ documentId }: { documentId: number }) { const sigCanvas = useRef<SignatureCanvas>(null); const [step, setStep] = useState<'draw' | 'confirm' | 'sms'>('draw'); const [smsCode, setSmsCode] = useState(''); const handleDrawComplete = async () => { if (sigCanvas.current?.isEmpty()) return; const signatureData = sigCanvas.current!.toDataURL('image/png'); // Сохранить изображение подписи, перейти к SMS-подтверждению await api.post(`/documents/${documentId}/initiate`, { signature_image: signatureData }); setStep('sms'); }; const handleSmsConfirm = async () => { await api.post(`/documents/${documentId}/confirm`, { code: smsCode }); setStep('confirm'); }; return ( <div> {step === 'draw' && ( <> <p>Нарисуйте вашу подпись:</p> <div style={{ border: '1px solid #e5e7eb', borderRadius: 8 }}> <SignatureCanvas ref={sigCanvas} penColor="#1a1a1a" canvasProps={{ width: 500, height: 200, className: 'signature-canvas' }} /> </div> <button onClick={() => sigCanvas.current?.clear()}>Очистить</button> <button onClick={handleDrawComplete}>Далее</button> </> )} {step === 'sms' && ( <> <p>Введите код из SMS для подтверждения подписи:</p> <input type="text" inputMode="numeric" maxLength={6} value={smsCode} onChange={e => setSmsCode(e.target.value)} /> <button onClick={handleSmsConfirm}>Подписать</button> </> )} {step === 'confirm' && ( <p>Документ успешно подписан. Копия отправлена на ваш email.</p> )} </div> ); } КЭП через СБИС / КриптоПро: максимальная юридическая сила
Для B2B и госзаказа внедряем квалифицированную электронную подпись. Подключение к СБИС или КриптоПро занимает 5–7 дней. Подписание происходит на стороне УЦ — мы только передаём документ и получаем подпись.
// Интеграция со СБИС API (подписание на стороне УЦ) class SbisSigningService { public function sign(string $documentBase64, int $signatoryId): string { $response = Http::withToken($this->getToken()) ->post('https://online.sbis.ru/service/sbis.Signature.Sign', [ 'jsonrpc' => '2.0', 'method' => 'СБИС.ПодписатьДокумент', 'params' => [ 'Документ' => $documentBase64, 'Подписывающий' => $signatoryId, ], ]); return $response->json('result.Подпись'); } } Хранение и проверка подписанных документов
// Верификация подписи — проверить, что документ не изменён после подписания public function verify(Document $document): bool { $currentHash = hash('sha256', Storage::disk('s3')->get($document->path)); return hash_equals($document->document_hash, $currentHash); } Подписанные документы храним с неизменяемыми правами (S3 Object Lock) — это предотвращает фальсификацию даже при компрометации аккаунта. Дополнительно настраиваем retention policy на 5 лет (срок исковой давности).
Что нужно для юридической значимости простой ЭП?
Для придания юридической силы простой ЭП необходимо: - Заключить соглашение об использовании ПЭП (оферта или договор присоединения) - Фиксировать время подписания, IP, User-Agent - Хранить аудит-лог всех действий (кто, когда, что подписал) - Использовать одноразовые SMS-коды с ограниченным сроком действия - Сохранять SHA-256 хэш документа в момент подписанияЧто входит в реализацию под ключ
| Этап | Состав работ | Длительность |
|---|---|---|
| Аналитика | Выбор типа ЭП, согласование юридической схемы | 1 день |
| Проектирование | Разработка архитектуры, UX подписания | 1–2 дня |
| Реализация ПЭП | SMS-код, хэш, аудит-лог, уведомления | 3–4 дня |
| Canvas + PDF-штамп | Визуальная подпись, встраивание в PDF | +2–3 дня |
| КЭП (СБИС/КриптоПро) | Интеграция с УЦ, регистрация подписантов | 5–7 дней |
| Хранилище | S3 Object Lock, retention, верификация | 1–2 дня |
| Документация и передача | API-спецификация, инструкция, обучение | 1 день |
Оценка точной стоимости и сроков — индивидуально после аудита текущей архитектуры. Получите консультацию по выбору типа подписи для вашего бизнеса — свяжитесь с нами.
Почему стоит заказать реализацию у нас
За 7 лет мы реализовали ЭП для 20+ проектов — от финтех-стартапов до госпорталов. Гарантируем юридическую чистоту и соответствие 63-ФЗ, 149-ФЗ и 152-ФЗ. Передаём полную документацию и доступ к исходному коду. Опыт работы с сертифицированными УЦ (СБИС, КриптоПро, Контур) подтверждён сертификатами.
Закажите аудит текущей системы подписания — мы найдём уязвимости и предложим оптимальное решение.







