Русский | English
Настольное приложение (C# / Avalonia UI) для подписания документов электронной подписью (ЭЦП) в формате CMS/PKCS#7 и работы с файлами подписей. Логика подписания портирована из сервиса подписания документов ReportGGE.
Скачать: готовый SignService.exe (Windows x64, .NET не требуется) — на странице
Releases.
- Drag & drop файлов и целых папок в окно программы, добавление через «Обзор…», пакетное подписание со статусом по каждому файлу; приём путей аргументами командной строки («Открыть с помощью»);
- откреплённая подпись (
имя.sigрядом с документом — формат госпорталов) или прикреплённая (документ внутри.sig); - усиленный формат CAdES-BES по умолчанию: подписанные атрибуты signing-time и signing-certificate-v2 (RFC 5035, защита от подмены сертификата); certHash для ГОСТ-2012 считается Стрибогом (собственная реализация ГОСТ Р 34.11-2012, проверенная на векторах RFC 6986);
- штамп времени (CAdES-T) по выбору: метка доверенного времени от службы TSA (RFC 3161), адрес настраивается; для ГОСТ-подписей запрос хешируется Стрибогом;
- ГОСТ через КриптоПро: на Windows подпись создаётся нативным CryptoAPI
(
CryptSignMessage) — криптопровайдер сертификата (КриптоПро CSP для ГОСТ) выполняет операцию и при необходимости запрашивает PIN-код; OID хеша подбирается по типу ключа (ГОСТ Р 34.10-2012 256/512, 34.10-2001, RSA/ECDSA); - в подпись вкладывается вся цепочка сертификатов (для офлайн-проверки), цепочка кешируется для пакетного подписания.
- подписи других лиц объединяются с вашей в один
.sig: программа сама находит подписи документа в его папке по содержимому — имя файла подписи может быть любым («договор-.pdf .sig»,.p7s,.p7m); у каждого файла выбирается «Добавить к „X.sig“ (8 подписантов)» или «Создать новую», а строка плана показывает, что произойдёт («будет добавлена подпись №9 к …»); переключатель «Добавить к существующей подписи / Создать новую» задаёт выбор по умолчанию. Подписи из других папок прикладываются кнопкой «+.sig» или перетаскиванием — к своему документу по содержимому; - перед заменой файла подписи без объединения и перед исключением подписантов программа спрашивает подтверждение и сохраняет резервную копию рядом; итог виден в строке файла: «Подписан: 9 (8 + ваша) → X.sig»;
- повторная подпись тем же сертификатом заменяет свою старую, а не дублирует;
- каждая объединяемая подпись проверяется криптографически: хеш документа, значение подписи и привязка сертификата CAdES — в том числе подписи КриптоПро с параметрами ГОСТ в signatureAlgorithm. Повреждённые подписи и подписи под другой версией исключаются с указанием подписанта; подписи, которые проверить не удалось (неизвестный алгоритм, нет сертификата), сохраняются и явно отмечаются;
- приложенная подпись другого лица или смена сертификата возвращают уже подписанный файл в очередь — его можно соподписать;
- входные подписи принимаются в DER/BER (включая неопределённые длины и «хвосты» файлов) и base64/PEM.
Операции доступны в меню «Инструменты» (с выбором файлов) и в контекстном
меню файла из списка (ПКМ) — тогда берётся имя.sig рядом с документом.
- Проверить ЭЦП… — проверка каждого подписанта CMS/CAdES: ГОСТ-2001, ГОСТ-2012 256/512, RSA и ECDSA без КриптоПро. Для откреплённой подписи выберите исходный документ; для прикреплённой он берётся из контейнера. Из контекстного меню («Подписанты и проверка ЭЦП…») проверка запускается сразу. Отчёт можно скопировать или сохранить в TXT;
- Объединить .sig… — несколько файлов подписей склеиваются в один со всеми подписантами (принимаются и прикреплённые контейнеры — документ сохраняется); если документ известен (по имени или найден по содержимому), результат — «документ.sig», существующий файл не затирается;
- Извлечь из .sig… — из криптоконтейнера достаются: вложенный документ
(байт-в-байт), откреплённая подпись со всеми подписантами и отдельные
.sigпо каждому подписанту (в имени — ФИО из сертификата); - Разделить групповую подпись… — отдельный откреплённый
.sigна каждого подписанта (вложенный документ сохраняется рядом); - Исключить подписанта из .sig… — подписант выбирается в списке (одинаковые ФИО различаются по серийному номеру сертификата); создаётся новый файл «имя (без подписанта).sig», исходный не меняется, последнего подписанта исключить нельзя;
- Собрать контейнер… — документ упаковывается в прикреплённый
.sigвместе с имеющимися подписями (обратная операция к извлечению); - Штамп на PDF… — копия документа с плашкой о подписании без подписи.
- кнопка «Добавить доверенность…» — как в Контуре: выбираются файл МЧД
(XML, формат EMCHD_1) и подпись руководителя (.sig;
имя.xml.sigрядом подхватывается автоматически); - программа проверяет подпись руководителя открытым ключом сертификата, срок действия МЧД и то, что представитель в МЧД — владелец выбранного сертификата: личный ИНН (12 цифр) и СНИЛС сверяются, если указаны с обеих сторон; ИНН организации из сертификата с ИНН физлица не сравнивается;
- сертификат руководителя, истёкший уже после выдачи МЧД, не отклоняет её — программа проверяет его на дату выдачи и предупреждает; истёкший до выдачи (или ещё не действовавший) — ошибка;
- при подписании файлы МЧД (XML + .sig) копируются рядом с подписанным документом (в CMS-подпись МЧД не вкладывается — так же поступает Контур), а в визуальный штамп на PDF добавляется строка «Действует на основании МЧД № …»;
- доверенность запоминается и перепроверяется в фоне при запуске и перед каждым пакетным подписанием (один раз на пакет).
- плашка «ДОКУМЕНТ ПОДПИСАН ЭЛЕКТРОННОЙ ПОДПИСЬЮ»: номер сертификата, владелец, срок действия, по желанию — дата подписания и логотип организации (PNG/JPEG);
- параметры выбираются в диалоге перед операцией: страницы (первая, последняя, все или указанные, например «1,3-5»), дата, логотип; на каждой выбранной странице — отдельная плашка на каждого подписанта;
- по умолчанию подписывается оригинал, а копия «имя (со штампом).pdf» — отдельный файл без подписи, который после каждого подписания пересоздаётся со всеми подписантами итоговой подписи (безопасно при соподписании: штамп не делает подписи недействительными);
- отдельной галочкой доступен режим «подписывать копию со штампом» (штамп до подписи) — для случаев, когда принимающая сторона требует подпись именно под штампованным документом.
- выбор из хранилища «Текущий пользователь → Личное», фильтр просроченных, выбранный сертификат запоминается;
- сохранение сертификата на компьютер (кнопка 💾), чтобы подписывать
без подключённого ключа ЭЦП:
- «в программе» — PFX-файл под паролем, виден только SignService;
- «в хранилище Windows» — копия ключа ставится в системное хранилище, подписывать смогут и другие программы (КриптоАРМ, браузер и т.д.); работает и для сертификата с токена (экспорт + установка одним действием);
- программа явно предупреждает о снижении безопасности; удаление — кнопкой 🗑 (PFX затирается; из хранилища удаляются только установленные программой записи); неэкспортируемые ключи сохранить нельзя — это ограничение токена/УЦ.
- лог операций всегда виден в главном окне — все действия с отметками времени;
- окно «Настройки…»: штамп времени (CAdES-T) и адрес службы TSA;
- окно «О программе»: версия, контакты автора, история версий, проверка обновлений;
- автообновление: проверка новых версий на GitHub Releases при запуске (отключается) и обновление в один клик из окна «О программе» (Windows); прежний exe сохраняется резервной копией и восстанавливается, если новая версия не запустилась.
Отчёт разделяет соответствие документу, значение подписи, привязку сертификата, цепочку доверия, статус отзыва и метку TSA. Корректная подпись сама по себе не подтверждает доверие к сертификату. Вложенный корень не становится доверенным: используются корни из хранилища ОС и явно выбранные в окне проверки сертификаты УЦ. Подписи сертификатов цепочки, CRL и OCSP проверяются управляемой библиотекой BouncyCastle.
По умолчанию проверка работает без сети. Для отзыва используются вложенные CRL
и выбранные файлы .crl/.ocsp. Сетевые запросы к HTTP(S) службам CRL/OCSP УЦ
включаются отдельной галочкой (настройка запоминается и действует и для МЧД).
Недоступный файл выбранного доверенного корня пропускается с предупреждением. Просроченные, неподписанные, неполные (в том числе
delta/indirect CRL) или недоступные доказательства дают неопределённый статус,
а не «сертификат действителен»; данные об отзыве проверяются для всех сертификатов
цепочки, кроме доверенного корня. Недостающие промежуточные сертификаты
должны присутствовать в CMS или хранилище ОС.
signing-time — время, заявленное самим подписантом. Исторический срок сертификата
оценивается по TSA только после проверки хеша, подписи, доверия и требуемого статуса
отзыва TSA. При получении метки проверяются также nonce и соответствие запросу.
МЧД перечитывается перед пакетным подписанием, проверяется и копируется как один снимок XML + SIG. Если сертификат руководителя истёк после выдачи МЧД, а метки TSA нет, время подписи не доказано — программа предупреждает и проверяет сертификат на дату выдачи. Конфликт с другим файлом МЧД останавливает операцию до сохранения подписи. Полномочия руководителя, содержание полномочий и отзыв самой МЧД в реестре не устанавливаются одной криптографической проверкой; при отсутствии подтверждений программа показывает предупреждение.
- Windows 10/11 — готовый exe со страницы Releases (самодостаточный);
- для создания ГОСТ-подписей — установленный КриптоПро CSP и личный сертификат;
- проверка и объединение ГОСТ-подписей работают без КриптоПро на Windows/Linux/macOS;
- сборка из исходников: .NET 8 SDK (Windows/Linux/macOS; вне Windows подписание доступно алгоритмами платформы — RSA/ECDSA, ГОСТ — только через CSP на Windows).
dotnet build SignService.sln -c Release
dotnet run --project src/SignService
dotnet run --project tests/SignService.Tests -c Release # тестыНа рабочем компьютере используйте -- --skip-user-store в конце команды тестов,
чтобы пропустить сценарии, изменяющие личное хранилище сертификатов и данные приложения.
Полный набор запускается в изолированном CI на Linux и Windows. Управляемые тесты
проверки ГОСТ, CRL/OCSP и TSA выполняются без КриптоПро и OpenSSL; интерфейс
проверяется без экрана (Avalonia.Headless).
Публикация самодостаточного exe:
dotnet publish src/SignService -c Release -r win-x64 --self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
-p:EnableCompressionInSingleFile=true \
-o publish- Запустите программу — в списке появятся сертификаты с закрытым ключом.
- Выберите сертификат, режим подписи и «Добавить к существующей подписи» или «Создать новую»; у каждого файла видно, к какой подписи добавится ваша. При необходимости включите штамп на PDF (параметры спросит диалог), штамп времени — в «Настройках…».
- Перетащите файлы в окно (или «Обзор…») и нажмите «Подписать» —
рядом с каждым файлом появится
имя.sig. - Операции с готовыми подписями — в меню «Инструменты» и в контекстном меню файла (ПКМ); ход работы виден в логе.
История изменений — в CHANGELOG.md и в окне «О программе».
Зайнуллин Марат Илгамович
- Телефон: +7-963-694-2461
- E-mail: zaynullinmi@gmail.com
- GitHub: https://github.com/zaynullinmi
src/SignService/
├── Services/
│ ├── CertificateProvider.cs # доступ к сертификатам (X509Store)
│ ├── DocumentSigner.cs # подпись CMS/PKCS#7: ГОСТ-OID, цепочка, кеш
│ ├── NativeSign.cs # CryptSignMessage (CryptoAPI) — ГОСТ через КриптоПро
│ ├── CadesAttributes.cs # атрибуты CAdES-BES: signing-time, signing-cert-v2
│ ├── Streebog.cs # ГОСТ Р 34.11-2012 для certHash (векторы RFC 6986)
│ ├── CmsMerger.cs # объединение/разбор/сборка подписей на ASN.1
│ ├── CmsExtractor.cs # файловые операции: извлечение, объединение, разделение
│ ├── SignatureDiscovery.cs # поиск подписей документа по содержимому
│ ├── SignatureVerifier.cs # проверка подписантов (BouncyCastle, ГОСТ без CSP)
│ ├── CertificateValidator.cs # цепочка доверия (PKIX) и хранилища ОС
│ ├── RevocationChecker.cs # отзыв сертификатов: CRL и OCSP
│ ├── PowerOfAttorneyService.cs # МЧД: разбор EMCHD_1, проверка, копирование
│ ├── BerDer.cs # нормализация BER → definite-length
│ ├── AtomicFile.cs # запись файлов через временный файл
│ ├── CertificateVault.cs # сертификат на ПК: PFX и хранилище Windows
│ ├── TimestampClient.cs # штамп времени TSA (RFC 3161) для CAdES-T
│ ├── PdfStamper.cs # визуальный штамп на PDF (страницы, подписанты, лого)
│ ├── UpdateService.cs # автообновление через GitHub Releases
│ └── AppSettings.cs # настройки (сертификат, режимы, штампы, доверие)
├── ViewModels/ # MVVM: главное окно, файлы, сертификаты
└── Views/ # окна: главное, проверка ЭЦП, штамп, подписанты, настройки…
tests/SignService.Tests/ # интеграционные тесты и смоук интерфейса (CI: Linux и Windows)
.github/release/ # сборка архива релиза: скрипт и тексты лицензий