3-Heights PDF Security

3-Heights PDF Security позволяет шифровать и расшифровывать PDF, задавать пароль владельца и пароль открытия, ограничивать печать, копирование и изменение, добавлять цифровые подписи PAdES и штампы, а также проверять сертификаты и встроенные данные долгосрочной валидации. Основной рабочий процесс строится вокруг открытия исходного документа, настройки защиты или подписи и сохранения результата в новый файл, поэтому исходник остаётся неизменным, а обработку удобно включать в серверный или пакетный сценарий.

Работа с документом организована через объект PdfSecure и связанные объекты подписи. Сначала вызывается Open или OpenMem, затем задаются параметры нужной операции: пароли и разрешения передаются при сохранении, свойства подписи настраиваются в PdfSignature, а штампы описываются отдельным XML-набором. Завершают цепочку SaveAs либо SaveInMemory и Close. Такая последовательность важна: часть параметров считывается только в момент формирования выходного PDF, поэтому преждевременное сохранение или повторное использование объекта без закрытия приводит к неверному результату.

Инструменты особенно полезны там, где один и тот же регламент применяется к большому числу файлов: выдача защищённых выписок, подписание счетов и актов, сертификация утверждённых шаблонов, добавление номера дела и служебной отметки, проверка входящих подписей. Вместо ручного открытия каждого документа приложение формирует параметры из учётной системы, выбирает сертификат, получает статус OCSP или CRL, записывает результат в отдельный каталог и сохраняет код ошибки для журнала.

Скачать 3-Heights PDF Security

Оценка 9.7 Рекомендуем
  • Редактирование PDF
  • Русский интерфейс
  • Просто новичкам
Скачать бесплатно на Windows
Лучшая альтернатива
3-Heights PDF Security
Оценка 8.5
  • Нет визуального редактора
  • Нужна лицензия
  • Сложная настройка PKCS#11
Скачать 3-Heights PDF Security
Загрузка начнётся после нажатия

Как устроен рабочий процесс

Обработка начинается с однозначного выбора входного файла и пароля, если документ закрыт от чтения. Open возвращает логический результат, а подробности отказа находятся в ErrorCode и ErrorMessage. После успешного открытия объект содержит разобранную структуру PDF, сведения о шифровании, подписи и ревизиях. Исходный файл при этом не переписывается: SaveAs требует другой путь, а попытка сохранить поверх входа должна рассматриваться как ошибка проектирования. Надёжный сценарий заранее создаёт временное имя в том же файловом разделе, проверяет итоговый код, закрывает объект и лишь затем атомарно перемещает новый файл в целевой каталог.

Операции можно комбинировать в одной записи. Например, приложение открывает договор, добавляет видимый штамп с номером заказа, формирует подпись с отметкой времени и сохраняет PDF с заданными разрешениями. Однако порядок влияет на юридический и технический результат. Любое изменение байтов после обычной подписи может сделать её недействительной; для допустимых последующих изменений используются инкрементальные ревизии и правила DocMDP. Поэтому сначала удаляют ненужные пустые поля, добавляют неизменяемое содержимое, затем формируют подпись и только после неё выполняют операции, прямо разрешённые политикой сертификации.

Для пакетной очереди один файл должен соответствовать одной независимой транзакции. Не следует переносить пароли, указатели на сертификат или состояние ошибки от предыдущего документа. После Close создаётся новый объект либо полностью переинициализируются все свойства. Такой подход предотвращает ситуацию, когда второй документ случайно получает визуальный текст, страницу или прямоугольник подписи, настроенный для первого.

Минимальная последовательность вызовов

  1. Создать объект PdfSecure и при необходимости установить лицензионный ключ до обработки первого файла.
  2. Открыть PDF методом Open с пустой строкой либо известным паролем; при отказе прочитать ErrorCode и ErrorMessage.
  3. Настроить пароли, разрешения, подпись, отметку времени или XML-штамп в зависимости от задачи.
  4. Сохранить результат через SaveAs либо SaveInMemory, не используя путь исходного документа.
  5. Проверить возвращаемое значение, закрыть объект и независимо проверить созданный PDF в валидаторе или просмотрщике.
PdfSecure document = new PdfSecure();
if (!document.Open(inputFile, inputPassword)) {
    Log(document.ErrorCode, document.ErrorMessage);
    return;
}
if (!document.SaveAs(outputFile, userPassword, ownerPassword, permissions)) {
    Log(document.ErrorCode, document.ErrorMessage);
}
document.Close();

Подключение к проекту и развёртывание библиотек

Пакет содержит управляемые сборки и нативные библиотеки, поэтому одной ссылки на .NET-сборку недостаточно. При запуске среда должна найти нативный файл нужной архитектуры. Для приложения Any CPU это означает, что фактическая разрядность процесса должна совпадать с размещённым вариантом библиотеки; на сервере с пулом приложений разрядность задаётся настройкой рабочего процесса. Типичная ошибка загрузки проявляется ещё до Open: среда сообщает об отсутствующем модуле, неверном формате образа или невозможности разрешить зависимость. Проверять нужно не PDF, а каталог развертывания, переменную поиска библиотек и архитектуру процесса.

В .NET подключают пространство имён PdfTools и добавляют ссылку на сборку интерфейса. Пакет рассчитан как на .NET Framework, так и на совместимые реализации .NET Standard, но нативная часть остаётся обязательной. При публикации self-contained нельзя полагаться только на автоматическое копирование управляемых DLL: каталог для выбранной системы и процессорной архитектуры включают в состав артефакта явно. Полезно добавить стартовую диагностику, которая выводит путь процесса, архитектуру, доступность нативной библиотеки и результат чтения ProductVersion; это сокращает поиск причин после переноса на другой сервер.

Подключение сборок 3-Heights PDF Security в проекте .NET

Интерфейсы C и C++ используют заголовки и импортные библиотеки, COM требует регистрации соответствующего бинарного компонента, а Java загружает нативную библиотеку через механизм JNI. Для COM особенно важно регистрировать 32-разрядную и 64-разрядную библиотеку правильной версией regsvr32; одинаковое имя утилиты в системных каталогах может вводить в заблуждение. В Java путь, указанный в java.library.path, должен быть доступен именно процессу службы, а не только интерактивному пользователю. При контейнерном запуске библиотеку и её системные зависимости копируют в образ, а путь задают до старта виртуальной машины.

Выбор компонента PDF Security в окне References Visual Basic

Старые проекты Visual Basic и C++ часто содержат жёстко прописанные каталоги. При переносе их лучше заменить конфигурацией, вычисляемой относительно каталога приложения. Абсолютный путь из рабочей станции разработчика может незаметно остаться в файле проекта и проявиться только на сборочном агенте. Отдельно проверяют права на каталог временных файлов, кэш и папку шрифтов: отсутствие права записи может выглядеть как ошибка подписи или штампа, хотя сертификат и исходный PDF исправны.

Настройки проекта для нативной библиотеки PDF Security

Каталоги библиотек в параметрах среды разработки

Открытие PDF и работа с паролями входного файла

Open принимает путь и пароль. Для незашифрованного файла передают пустую строку. Документ, защищённый только паролем владельца, обычно также открывается с пустой строкой, потому что чтение не ограничено. Если задан пароль пользователя, нужен либо он, либо пароль владельца. После успешного открытия библиотека получает полный доступ к содержимому; различать полномочия пользователя и владельца должно вызывающее приложение. Например, веб-система не должна разрешать смену защиты лишь потому, что технический сервисный аккаунт смог открыть файл с пользовательским паролем.

Код PDF_E_PASSWORD следует обрабатывать отдельно от повреждения документа. Он означает, что файл распознан, но переданные учётные данные не подходят. Практичный интерфейс не повторяет операцию бесконечно: он ограничивает число попыток, не пишет пароль в журнал и возвращает пользователю нейтральное сообщение. В фоновой очереди такой документ помещают в отдельный статус ожидания секрета, а не повторяют с теми же параметрами при каждом цикле.

Необходимо различать пустой пароль и отсутствие значения в бизнес-логике. По спецификации пустая строка является допустимым паролем, и программы чтения пробуют её автоматически. Поэтому поле базы данных NULL, пустая строка и намеренное снятие пароля должны иметь разные значения. Иначе пакетная задача может зашифровать PDF так, что он открывается без запроса, хотя оператор ожидал реальную защиту.

Шифрование и модель двух паролей

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

Шифрование применяется к строкам и потокам, включая текст и изображения, но общая структура PDF остаётся видимой. Это нормальное устройство формата, а не признак ошибки. Защита не скрывает сам факт наличия страниц, объектов и метаданных так, как это сделал бы зашифрованный контейнер. Если политика требует скрывать также имя файла, размер и служебные атрибуты, PDF дополнительно помещают в защищённое хранилище или транспортный контейнер.

Параметры защиты передаются при SaveAs. Наличие любого пароля или разрешений включает шифрование. Для полного отказа от него используются пустые пароли и специальное значение ePermNoEncryption. Нельзя считать, что пустые строки сами по себе всегда отключают защиту: если вместе с ними передан набор ограничений, выходной документ всё равно должен иметь пароль владельца и соответствующий security handler. Вызывающее приложение должно формировать эти четыре поля как единую политику, а не как независимые флажки формы.

document.SaveAs(outputFile, "", "owner-secret", ePermPrint);
// Открытие без запроса, но разрешена только печать.

document.SaveAs(outputFile, "reader-secret", "owner-secret", ePermPrint);
// Для чтения нужен пароль; печать остаётся разрешённой.

document.SaveAs(outputFile, "", "", ePermNoEncryption);
// Выходной PDF без стандартного шифрования.

Сильный пользовательский пароль важнее формального запрета копирования. Короткие словарные комбинации перебираются быстро, а пароль владельца без пароля открытия не препятствует извлечению содержимого программой, которая игнорирует permission flags. Для документов с персональными данными применяют длинную случайную фразу, передают её отдельным каналом и не включают в имя файла, XML-штамп, текст подписи или системный журнал.

Разрешения PDF

Флаги разрешений описывают, что совместимый просмотрщик позволяет делать после открытия: изменять содержимое, копировать текст и графику, создавать или менять аннотации и поля формы, печатать с низким либо высоким качеством, заполнять формы и подписывать, собирать документ из страниц. Они работают только вместе с шифрованием и паролем владельца. Если бизнес-правило говорит разрешить заполнение и подпись, запретить правку текста, набор должен включать соответствующие разрешения формы и подписи, но не общее изменение содержимого.

  • Печать задаётся отдельно от изменения; для некоторых профилей можно разрешить только пониженное качество.
  • Копирование охватывает извлечение текста и графики, но не является средством защиты от фотографирования экрана.
  • Сборка документа относится к вставке, удалению, повороту и перестановке страниц.
  • Аннотации и формы следует проверять раздельно, если получатель должен заполнить поля, но не добавлять произвольные комментарии.
  • Полный доступ выдаёт пароль владельца независимо от набора ограничений, поэтому его нельзя передавать обычному читателю.

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

Расшифрование и смена защиты

Для снятия или замены защиты сначала открывают файл с подходящим паролем, затем сохраняют новый PDF с другой комбинацией параметров. Исходный security handler не редактируется на месте. Чтобы полностью убрать стандартное шифрование, в SaveAs передают пустые пароли и ePermNoEncryption. Чтобы сменить только пароль открытия, задают новое пользовательское значение и обязательно контролируют пароль владельца; оставленный пустым владелец может стать равным пользовательскому паролю.

Массовое расшифрование допустимо только после проверки полномочий. Технически библиотека может открыть документ с паролем владельца и выдать незашифрованную копию, но такая возможность не заменяет аудит. В журнал записывают идентификатор задания, хэш входа, хэш результата и основание операции, однако не пароль. При ошибке выходной файл удаляют: частично записанный PDF не должен попадать в каталог обмена.

При работе с подписанным файлом изменение шифрования создаёт новую версию содержимого и обычно нарушает существующие подписи. Если подпись должна оставаться проверяемой, нельзя просто пересохранить документ с новым паролем. Сначала определяют разрешённые изменения по DocMDP и профилю подписи; чаще защищённую доставку организуют вокруг уже подписанного файла, не меняя его байты.

Подготовка цифровой подписи

Подпись создаётся отдельным объектом PdfSignature. До AddSignature задают место хранения закрытого ключа, сертификат, причину, контакт, место, видимый прямоугольник, страницу и параметры PAdES. AddSignature лишь добавляет описание операции к документу; криптографическая запись завершается во время SaveAs или SaveInMemory. Поэтому успешный AddSignature ещё не доказывает, что закрытый ключ доступен, сертификат действителен и сервер отметок времени отвечает. Окончательный статус всегда берут после сохранения.

Подписывается байтовое представление PDF, а не картинка штампа. Видимый прямоугольник помогает человеку найти подпись, но его отсутствие не означает отсутствия криптографической подписи. И наоборот, вставленное изображение рукописной подписи не создаёт проверяемой связи с сертификатом. В интерфейсе получателя нужно показывать оба слоя: внешний вид на странице и результат проверки цепочки, целостности, времени и отзыва.

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

Пример визуального представления подписи

Выбор сертификата и закрытого ключа

Для создания подписи нужен сертификат и соответствующий закрытый ключ. Сертификат содержит открытый ключ и данные владельца; закрытый ключ остаётся в хранилище, файле, токене или HSM. Указывать только отображаемое имя рискованно: в хранилище могут находиться два сертификата с одинаковым субъектом, но разными серийными номерами, сроками или назначением ключа. Надёжный выбор использует отпечаток, серийный номер либо сочетание хранилища, провайдера и имени, а после выбора проверяет наличие private key и допустимый Key Usage.

На Windows сертификаты пользователя и компьютера находятся в разных контекстах. Служба, запущенная под отдельной учётной записью, не видит личное хранилище разработчика. Сертификат нужно установить в доступный контекст и предоставить процессу право на закрытый ключ. Наличие строки в MMC не гарантирует право подписи: открытая часть может отображаться, а обращение к ключу завершаться отказом доступа. Проверку выполняют под той же учётной записью и в том же режиме, в котором работает производственный процесс.

Хранилище сертификатов Windows

В окне сертификата вкладка General показывает назначение, издателя, владельца и период действия. Сообщение о наличии закрытого ключа является важным, но не полным признаком: ключ может находиться на отключённом токене или требовать PIN. На вкладке Details проверяют Enhanced Key Usage и Key Usage, отпечаток и серийный номер. В Certification Path контролируют построение цепочки до доверенного корня.

Общие сведения о сертификате

Подробные поля сертификата

Цепочка сертификации

Истёкший сертификат, сертификат без права цифровой подписи и сертификат, отозванный до момента операции, не должны использоваться. При наличии доверенной отметки времени истечение сертификата после подписания не обязательно делает прежнюю подпись недействительной, но это вывод проверки, а не разрешение подписывать просроченным ключом сегодня. Система выбора должна фильтровать кандидатов по текущей дате, назначению и доступности ключа до запуска SaveAs.

PKCS#11, токены и HSM

Для USB-токенов, смарт-карт и аппаратных модулей безопасности предпочтителен PKCS#11. В конфигурации указывают библиотеку поставщика устройства, слот или токен, идентификатор ключа и PIN либо механизм его безопасного получения. Путь к PKCS#11-модулю должен соответствовать архитектуре процесса. Загрузка 32-разрядной библиотеки в 64-разрядный процесс приводит к ошибке формата ещё до обращения к сертификату.

Токен может хранить только закрытый ключ, а цепочка сертификатов — отсутствовать или быть неполной. В таком случае промежуточные сертификаты добавляют из доверенного каталога или системного хранилища. Если цепочка не строится, подпись может криптографически создаться, но получатель не сможет подтвердить доверие или получить статус отзыва. Перед массовой работой тестируют не только подпись одного файла, но и формирование PAdES-LT с встраиванием всей необходимой цепочки.

PIN нельзя хранить в открытом конфигурационном файле рядом с приложением. Для службы используют защищённое хранилище секретов, а для интерактивного токена — контролируемый запрос. Устройства могут блокироваться после нескольких неверных попыток, поэтому автоматический повтор должен распознавать ошибку аутентификации и останавливаться. Перезапуск задания с тем же неправильным PIN не является восстановлением.

Параллельная подпись через один PKCS#11-провайдер требует отдельной проверки потокобезопасности. Некоторые драйверы поддерживают одну сессию или сериализуют операции внутри. Без ограничителя несколько рабочих потоков могут взаимно закрывать сессии, запрашивать PIN или получать неверный объект ключа. Практичная очередь выделяет отдельный worker на токен либо использует пул строго управляемых сессий и измеряет реальную пропускную способность на целевом HSM.

Визуальное представление подписи

Прямоугольник подписи задаётся номером страницы и координатами. Координатная система PDF может отличаться от экранных пикселей, а повёрнутая страница добавляет преобразование. Перед массовой подписью создают тесты для книжной, альбомной и повёрнутой страницы, а также для CropBox, отличающегося от MediaBox. Иначе подпись оказывается за видимой областью или на соседнем месте.

Внешний вид включает фон, рамку, толщину линии, два текстовых блока, шрифты, размеры и цвета, а также изображение. FillColor равный -1 оставляет фон прозрачным, что удобно при использовании логотипа или скана печати. Цвет передаётся числом RGB по формуле red + green×256 + blue×256×256; ошибочный порядок каналов даёт неожиданный оттенок. Цветовые значения лучше вычислять общей функцией и покрыть тестами.

Text1 и Text2 используются как верхняя и нижняя части подписи. В них помещают только данные, которые действительно помогают получателю: имя подписанта, роль, причину и проверяемое время. Не следует выводить секретные идентификаторы, PIN, путь к ключу или внутренний адрес службы. Текст должен помещаться при самой длинной фамилии и локализованной причине; автоматическое уменьшение шрифта лучше предусмотреть в вызывающем коде.

FontName1 и FontName2 принимают имя установленного шрифта либо путь к файлу. Шрифт должен быть доступен учётной записи процесса. Для воспроизводимого серверного результата удобнее поставлять разрешённый к распространению файл шрифта и задавать его явно либо передавать через Font1Mem и Font2Mem. Это исключает зависимость от набора шрифтов конкретного узла и различия между интерактивной сессией и службой.

Предварительный просмотр перед подписью

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

Такой режим полезен, когда подписант выбирает место на странице или должен увидеть итоговую печатную форму до обращения к ключу. Предварительный файл необходимо маркировать как неподписанный и не выдавать его за окончательный. После отказа его удаляют, а после подтверждения сверяют идентификатор задания, хэш и имя поля. Это предотвращает подмену предпросмотра другим документом в параллельной сессии.

PAdES: выбор уровня подписи

Уровень PAdES определяет, какие доказательства включаются в документ. PAdES-B-B содержит базовую подпись и обязательные атрибуты. PAdES-B-T добавляет доверенную отметку времени к подписи. PAdES-B-LT включает материалы долгосрочной проверки: сертификаты и сведения об отзыве. PAdES-B-LTA дополняет их архивной отметкой времени, защищающей набор доказательств и позволяющей продлевать проверяемость новыми временными отметками.

Выбор должен исходить из срока хранения и инфраструктуры получателя. Для краткоживущего внутреннего согласования может быть достаточно базового уровня, если проверка выполняется сразу. Для договоров и архивных документов обычно важны время, цепочка и данные отзыва, чтобы проверять подпись после истечения сертификата. Название уровня в настройке не гарантирует результат: сеть, TSA, OCSP и цепочка должны реально сработать, а выходной документ нужно валидировать.

При создании B-T сервер времени подтверждает, что подпись существовала не позднее указанного момента. Локальные часы компьютера для этого недостаточны. Для LT нужны валидные ответы OCSP или CRL по сертификату подписанта и промежуточным сертификатам. Для LTA архивная отметка охватывает уже встроенные данные. Если одна из сетевых операций не завершилась, нельзя автоматически понижать уровень без явного бизнес-правила: пользователь может получить подпись, не отвечающую регламенту.

Отметка времени

TimeStampURL задаёт службу TSA, а TimeStampCredentials — данные доступа, если она требует аутентификацию. Отпечаток сертификата TSA можно ограничить через TimeStampFingerprint, чтобы не принять неожиданный сертификат при ошибочной конфигурации. Перед производственным запуском проверяют доступность адреса из сети сервера, доверие к цепочке TSA, поддерживаемый алгоритм и максимальную задержку.

Отметка времени может быть атрибутом обычной подписи или отдельной document timestamp signature. Это разные объекты. Отдельная временная подпись подтверждает состояние документа и используется при продлении LTA; она не сообщает, кто одобрил содержание. Интерфейс проверки должен различать сертификат подписанта и сертификат службы времени.

Отметка времени в свойствах цифровой подписи

Ошибка TSA не всегда вызвана сертификатом документа. Частые причины — DNS, прокси, запрет исходящего соединения, неверные учётные данные, неподдерживаемый алгоритм и недоверенная цепочка сервера. В журнал помещают код операции и имя профиля TSA, но не пароль. При временном сбое допустим ограниченный повтор с паузой; при отказе аутентификации или несовместимом ответе повтор без изменения конфигурации бессмыслен.

OCSP, CRL и долгосрочная проверка

Сведения об отзыве доказывают, что сертификат не был отозван на момент проверки. OCSP даёт подписанный ответ службы статуса, CRL представляет подписанный список отозванных сертификатов. В одной цепочке могут использоваться оба механизма. Для PAdES-LT ответы должны быть встроены в подпись или документ, а не просто получены просмотрщиком при открытии. Фраза действителен сейчас без сохранённого доказательства не обеспечивает проверку спустя годы.

EmbedRevocationInfo включает получение данных для сертификата подписанта и цепочки. Это увеличивает файл, обычно на десятки килобайт, и добавляет сетевую задержку. Если OCSP недоступен, SaveAs может завершиться ошибкой SIG_CREA_E_OCSP. Убирать этот флаг ради успешного завершения нельзя без решения владельца процесса: получится другой профиль подписи.

Проверка отзыва сертификата по OCSP

В корпоративной сети прокси должен пропускать нужные запросы и ответы, включая MIME-типы application/ocsp-request и application/ocsp-response. Настройки ProxyURL и ProxyCredentials задают маршрут для сетевых служб. При диагностике отдельно проверяют соединение с TSA, OCSP и точками загрузки CRL: доступ к одному адресу не означает доступность остальных. TLS-перехват корпоративным шлюзом также может изменить цепочку сервера и вызвать ошибку доверия.

Кэш OCSP, CRL и ответов TSA сокращает задержку при массовой подписи. Он должен быть общим для процессов, которым разрешено использовать одни и те же данные, доступным на запись и защищённым от несанкционированной подмены. Срок действия ответа проверяется при каждом использовании; старый OCSP нельзя считать бессрочным. Свойство NoCache применяют осознанно: отключение кэша повышает число сетевых обращений и нагрузку на внешние службы.

Проверка цифровых подписей

Проверка должна отвечать как минимум на четыре вопроса: неизменны ли подписанные байты, строится ли доверенная цепочка, был ли сертификат действителен и не отозван, подтверждено ли время. Один зелёный индикатор без расшифровки недостаточен. В отчёте указывают каждую подпись, охваченную ревизию, субъект и издателя сертификата, алгоритм, время, способ получения данных отзыва и результат политики DocMDP.

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

Проверка цепочки доверия подписи

Статус отзыва проверяют для подписанта и всех не корневых сертификатов цепочки. Ответ должен относиться к нужному серийному номеру, быть подписан доверенной службой и охватывать проверяемый момент. Если данные встроены в документ, проверяют их подпись и время действия, а не просто факт наличия объекта DSS. Если данные получены из сети во время просмотра, отчёт должен отличать их от доказательств, сохранённых при подписании.

Для PAdES-LTV дополнительно проверяют, что доказательства встроены и срок их применимости соответствует подписи. В старом Adobe Reader вкладки Trust, Revocation и Date/Time показывают отдельные аспекты; современная автоматическая проверка должна сохранять такую же детализацию в машинном отчёте. Это позволяет понять, почему подпись не прошла: повреждение байтов, недоверенный корень, отзыв, отсутствие TSA или неполный LT-набор.

DocMDP и сертификация документа

AddDocMDPSignature создаёт сертифицирующую подпись, задающую разрешённые изменения. В документе может быть только одна такая подпись, и она должна быть первой. Значение разрешений 1 запрещает любые изменения; 2 допускает заполнение форм, создание экземпляров шаблонов страниц и последующие подписи; 3 дополнительно допускает создание, удаление и изменение аннотаций. Иные изменения делают подпись недействительной с точки зрения политики.

DocMDP не следует смешивать со стандартным шифрованием без тщательно проверенного сценария. Сертификация отвечает за обнаружение изменений, а парольная защита — за доступ и разрешения просмотра. Совмещение может ухудшить совместимость и усложнить последующую подпись. Для формы, которую должны заполнить и подписать несколько участников, обычно выбирают разрешение 2 и заранее создают поля; для комментирования — 3.

Сертифицирующая подпись использует возможности PDF 1.6. Поэтому применение к PDF/A-1 требует особой осторожности и принудительного режима, который может затронуть соответствие. В архивном процессе лучше заранее выбрать допустимый профиль PDF/A и проверить итог специализированным валидатором. Нельзя считать файл соответствующим только потому, что исходник имел метку PDF/A.

Подписи, ревизии и инкрементальные обновления

Подписанный PDF хранит последовательность ревизий. RevisionCount показывает их число, а методы получения ревизии позволяют анализировать состояние документа на конкретном этапе. Линеаризованный файл может физически напоминать обновлённый, но считается одной ревизией. При расследовании важно сравнивать не только последний вид страницы, но и то, какие объекты добавлены после каждой подписи.

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

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

Подписи, аннотации и ревизии документа

Штампы: текст, изображения и графика

Штамп добавляет новое видимое содержимое: текст, изображение или векторные примитивы. Описание передаётся XML-файлом через AddStamps либо буфером через AddStampsMem. Один XML может содержать несколько штампов для разных страниц и координат. Это удобно для номера документа, статуса, даты, водяного знака, штрихкода, логотипа подразделения и служебной ссылки.

Разметка штампа должна формироваться как структурированный XML, а не склеиваться строкой из непроверенных данных. Значения из базы экранируют, кодировку фиксируют, а длину текста ограничивают. Иначе символы амперсанда или угловые скобки делают файл недействительным, а длинный номер выходит за рамку. Для каждого шаблона полезно хранить тестовый PDF с ожидаемым изображением и сравнивать его после обновления библиотек.

Текстовые элементы зависят от доступных шрифтов. Если шрифт не найден, результат может отличаться по метрикам или операция завершится ошибкой. Для кириллицы выбирают шрифт с нужным набором знаков и проверяют встраивание. Цвет, прозрачность, масштабирование, поворот и преобразования задают явно; значения по умолчанию не должны быть частью неформального знания разработчика.

Изображения следует готовить с достаточным разрешением, но не хранить многомегапиксельный логотип для маленькой отметки. PDF может повторно использовать один ресурс, однако разные файлы и прозрачности увеличивают размер. Для печати оценивают физический размер на странице, а не только число пикселей. Прозрачный PNG проверяют на белом и цветном фоне.

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

Обработка в памяти

OpenMem открывает PDF из буфера, SaveInMemory формирует результат без промежуточного файла, а GetPdf возвращает выходной блок. Это подходит для очередей сообщений, объектов в базе и HTTP-потоков. Но отсутствие дискового файла не отменяет потребление памяти: библиотека хранит вход, разобранные структуры и выход. Максимальный размер запроса должен учитывать несколько копий и параллельные задания.

Буфер нельзя освобождать раньше завершения OpenMem, а результат GetPdf нужно скопировать или передать дальше в соответствии с правилами интерфейса. В управляемом коде важно не удерживать большие массивы дольше необходимого: после отправки результата ссылки освобождают, объект закрывают. Для сотен крупных документов потоковая очередь с ограничением параллелизма надёжнее, чем запуск задачи на каждый запрос.

PdfSecure first = new PdfSecure();
first.OpenMem(inputBytes, password);
first.SaveInMemory("", "owner-secret", permissions);
byte[] protectedPdf = first.GetPdf();
first.Close();

При цепочке нескольких операций можно передать GetPdf следующему объекту через OpenMem. Однако каждое полное пересохранение меняет байты и может влиять на подписи. Лучше объединять совместимые операции в одном объекте и сохранять один раз. Отдельные этапы оправданы, когда между ними выполняется внешнее одобрение или криптографическая подпись удалённым сервисом.

Удалённое подписание

Закрытый ключ может находиться у удалённого провайдера подписи. В таком процессе библиотека подготавливает хэш и необходимые атрибуты, сервис выполняет криптографическую операцию после аутентификации пользователя или организации, а результат встраивается в PDF. Конфигурация зависит от провайдера: требуются учётные данные, идентификатор ключа, профиль подписи, адрес службы и иногда одноразовое подтверждение.

Сетевой сервис нельзя воспринимать как обычный файл сертификата. Операция имеет состояние: запрос создан, пользователь подтвердил, подпись получена, PDF завершён. Повтор после тайм-аута должен быть идемпотентным, иначе один документ подпишется несколько раз или счёт провайдера получит лишнюю транзакцию. Система хранит correlation ID и выясняет статус прежнего запроса до создания нового.

Прокси, межсетевой экран и TLS-проверка применяются и к удалённой подписи, и к TSA/OCSP. Для диагностики полезны отдельные проверки маршрута, но секреты не выводят в trace. При недоступности сервиса подготовленный документ и контекст подписи хранят ограниченное время, защищают от подмены и удаляют после завершения либо отмены.

Кэш, временные файлы и шрифты

Каталог временных файлов используется при операциях, для которых недостаточно памяти или требуется промежуточное представление. Он должен существовать, иметь достаточно места и права для учётной записи процесса. Сетевой каталог увеличивает задержку и добавляет новый класс сбоев; локальный быстрый диск с контролируемой очисткой обычно предсказуемее. Имя временного файла не должно раскрывать пароль или содержимое документа.

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

На Windows шрифт, установленный только для одного пользователя, может быть невидим службе. Решение — установка для всех пользователей, запуск под нужным профилем либо явный путь к файлу. На Linux и macOS проверяют права, регистр и фактическое расположение. Для текста подписи и штампа контрольный тест должен содержать кириллицу, цифры, знаки валют и символы, используемые в реальных данных.

Ошибки и журналирование

Большинство методов возвращает True или False. При False читают ErrorCode и ErrorMessage немедленно, до следующего вызова, который может изменить состояние. Код используют для машинной классификации, текст — для диагностики. Нельзя строить логику по фрагменту английского сообщения: формулировка может измениться, а разные причины иметь похожий текст.

Ошибки удобно делить на входные, инфраструктурные и криптографические. К входным относятся неверный пароль, повреждённый PDF и недопустимый XML штампа. Инфраструктурные включают отсутствие библиотеки, каталогов, места, шрифта и сетевого доступа. Криптографические — недоступный ключ, неверный PIN, истёкший или неподходящий сертификат, отказ TSA и отсутствие данных отзыва. Для каждой группы задают своё действие: исправление данных, повтор после восстановления среды или остановку с обращением к администратору ключа.

Trace помогает разработчику увидеть последовательность вызовов и внутренние этапы. Документация указывает, что содержимое файлов и пароли в трассировку не включаются, однако сам журнал всё равно может содержать пути, имена сертификатов и сетевые параметры. Его хранят ограниченное время и передают только по защищённому каналу. В обычном режиме подробный trace выключают из-за объёма и влияния на производительность.

  • PDF_E_PASSWORD: запросить другой пароль или перевести задание в ожидание секрета; повтор с тем же значением не поможет.
  • SIG_CREA_E_OCSP: проверить сеть, прокси, адреса статуса и срок действия ответов; не понижать профиль подписи молча.
  • Ошибка загрузки модуля: сверить архитектуру процесса, каталог нативных библиотек и системные зависимости.
  • Ошибка шрифта: проверить доступность файла для учётной записи, каталог кэша и наличие нужных глифов.
  • Ошибка XML штампа: валидировать XML до вызова, проверить кодировку, экранирование и обязательные атрибуты.
  • Ошибка SaveAs: убедиться, что выходной путь отличается от входного, каталог существует и доступен на запись.

Практическая диагностика типовых сбоев

Документ не открывается

Сначала проверяют первые байты и размер файла, затем открывают его независимым просмотрщиком. Если просмотрщик просит пароль, различают пароль открытия и владельца. После PDF_E_PASSWORD не следует пробовать пустую строку в цикле. Если файл повреждён, ошибка может проявляться на конкретной ревизии; полезно сохранить исходник и не пытаться исправить его тем же процессом защиты.

Подпись создаётся, но отображается как недоверенная

Криптографическая целостность и доверие — разные результаты. Проверяют цепочку, доверенный корень, промежуточные сертификаты, Key Usage, время и отзыв. На машине разработчика цепочка могла быть установлена вручную, а на сервере или у получателя её нет. Для LT-профиля нужные материалы встраивают, а корневую политику получатель всё равно определяет самостоятельно.

Подпись находится за страницей или обрезана

Проверяют номер страницы, единицы координат, MediaBox, CropBox и Rotate. На тестовом PDF рисуют временную рамку и подпись на всех четырёх углах. Координаты, полученные из веб-просмотрщика, пересчитывают из пикселей с учётом масштаба и начала координат. После подтверждения рамку убирают, но регрессионный тест сохраняют.

Штамп содержит квадраты вместо русских букв

Причина обычно в шрифте или кодировке XML. Указывают Unicode-совместимый шрифт, доступный процессу, и сохраняют XML в согласованной кодировке. Проверяют, что выбранный файл действительно содержит кириллические глифы. Кэш шрифтов перестраивают после замены файла.

Массовая подпись постепенно замедляется

Измеряют время открытия, хэширования, обращения к HSM, TSA, OCSP и сохранения отдельно. Если растёт сетевой этап, проверяют кэш и лимиты внешней службы. Если растёт память, убеждаются, что Close вызывается, буферы GetPdf освобождаются и объекты не удерживаются журналом. Не увеличивают число потоков без измерения PKCS#11-провайдера.

Сценарии применения

Защищённая выдача персональной выписки

Система формирует PDF, открывает его без пароля, сохраняет с длинным пользовательским паролем и отдельным владельцем, запрещает изменение и копирование, при необходимости разрешает печать. Пароль передаётся через другой канал. После сохранения тестовый процесс пытается открыть файл без пароля и с неверным паролем, затем проверяет разрешения. Исходный незашифрованный файл удаляется по политике хранения только после успешной проверки результата.

Подписание счетов организационной печатью

Очередь получает готовый счёт, добавляет номер операции в видимый текст подписи, выбирает ключ организации в HSM, запрашивает TSA и данные отзыва, создаёт PAdES-LT либо LTA и отправляет PDF в архив. В журнале сохраняются хэши, серийный номер сертификата, идентификатор TSA и итог валидации. При недоступности OCSP задание ждёт восстановления, а не выпускает более слабую подпись.

Сертифицированная форма для последующего заполнения

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

Штамп маршрута согласования

XML-шаблон размещает номер дела, подразделение и дату в фиксированной области каждой нужной страницы. Значения экранируются, шрифт поставляется вместе с системой, длина строк ограничена. Если документ уже подписан, отметка добавляется только как разрешённая аннотация в новой ревизии; иначе она включается до первой подписи.

Проверка входящих документов

Сервис перечисляет подписи и ревизии, проверяет байтовую целостность, цепочку, отзыв, отметку времени и DocMDP. Результат не сводится к одному флагу: бизнес-правило может принять действительную подпись от известного центра, отправить неизвестный корень на ручную проверку и отклонить изменение после подписи. Оригинал сохраняется без пересохранения, чтобы не менять доказательства.

Совместимость форматов и ограничения

Входом и выходом служит PDF, включая документы поколений PDF 1.x и PDF 2.0. Инструмент не конвертирует Word, изображения или электронные таблицы в PDF; такой этап выполняют до защиты. Он также не является редактором текста и страниц. Если нужно исправить опечатку, переставить страницы или распознать скан, это делают раньше, потому что последующее редактирование способно нарушить подпись.

Подписи рассчитаны на PDF/A-согласованные процессы, но шифрование несовместимо с принципом PDF/A: архивный документ должен оставаться доступным без секретного алгоритма и пароля. Поэтому защищённую паролем копию нельзя автоматически считать PDF/A, даже если исходник прошёл проверку. При сочетании архивного хранения и конфиденциальной доставки сохраняют отдельный неизменённый архивный экземпляр в контролируемом хранилище и защищённую транспортную копию.

Некоторые конструкции зависят от поколения PDF. DocMDP появился в PDF 1.6, а определённые timestamp-механизмы связаны с более новыми возможностями. Принудительное добавление может изменить профиль соответствия. После каждой такой операции нужен независимый валидатор, а не только успешное возвращаемое значение SaveAs.

Интерфейсы .NET, Java, COM и C/C++ имеют сходную последовательность вызовов, но типы буферов, управление памятью и загрузка нативных библиотек различаются. Код из примера одного интерфейса нельзя копировать буквально в другой. Общим остаётся порядок: открыть, настроить, добавить операции, сохранить, проверить ошибку, закрыть.

Безопасность процесса вокруг программы

Криптографическая функция не компенсирует небезопасное хранение секретов. Пароль владельца, PIN токена, учётные данные TSA и прокси должны находиться в менеджере секретов, а доступ к ним выдаётся только сервисной учётной записи. Конфигурационные файлы не помещают в общий каталог публикации и не включают в диагностический архив.

Закрытый ключ не экспортируют из HSM ради упрощения развёртывания. Вместо этого настраивают PKCS#11, права и резервный модуль согласно политике ключей. Для программного контейнера ограничивают права на файл, шифруют хранилище и контролируют резервные копии. Смена сертификата должна быть штатной процедурой: система выбирает ключ по конфигурации, а не по первому совпавшему имени.

Входные PDF рассматривают как недоверенные данные. Ограничивают размер, число страниц, время обработки и память; задания выполняют под учётной записью без лишних прав. Временный каталог не должен быть исполняемым и общедоступным. После сбоя остатки очищаются, но исходник сохраняется для расследования в карантине.

Итоговый файл проверяют до выдачи. Минимум включает открытие, число страниц, наличие ожидаемой подписи или шифрования и отсутствие ошибки в структуре. Для юридически значимого процесса добавляют профильную валидацию PAdES и PDF/A, проверку хэша и журнал неизменяемых событий. Успех SaveAs означает, что библиотека завершила запись, но не заменяет проверку бизнес-требований.

Алгоритмы шифрования и совместимость просмотрщиков

Свойства StreamCryptFilter и StringCryptFilter позволяют управлять способом шифрования потоков и строк. Поддерживаются варианты RC4, AESV2 и AESV3; AESV2 использует 128-битный AES, AESV3 — 256-битный. Для новых процессов разумно выбирать AES, а RC4 оставлять только для строго обоснованной совместимости со старым получателем. Программа просмотра должна поддерживать выбранный security handler и поколение PDF, иначе пользователь увидит сообщение о неподдерживаемом шифровании, хотя пароль верен.

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

Некоторые просмотрщики требуют одинаковый фильтр для строк и потоков. Разные значения могут соответствовать формату, но ухудшить совместимость. Если нет специальной причины разделять их, для обоих типов выбирают один AES-профиль. После сохранения тестируют открытие в целевых клиентах, извлечение вложений, отображение изображений и метаданных, потому что разные части PDF шифруются как строки или потоки.

Выбор AES-256 не компенсирует слабый пользовательский пароль. Ключ защиты PDF выводится из пароля по правилам security handler, поэтому короткая словарная фраза остаётся основной уязвимостью. Генератор паролей должен обеспечивать достаточную энтропию, а канал передачи — исключать отправку вместе с файлом. Для машинного обмена пароль лучше получать из секретного хранилища по идентификатору документа и удалять из памяти после SaveAs.

Хэширование и алгоритм подписи

Для формирования подписи сначала вычисляется дайджест документа. Типичное значение MessageDigestAlgorithm — SHA-256; SHA-1 следует считать устаревшим и применять только при неизбежном требовании старой инфраструктуры. Более сильный хэш должен поддерживаться криптопровайдером и устройством. Если HSM не реализует запрошенный механизм, операция завершится ошибкой, поэтому список алгоритмов проверяют на реальном ключе, а не только в документации устройства.

Свойство SigAlgo выбирает способ RSA-подписи. RSA_RSA соответствует широко поддерживаемой схеме PKCS#1 v1.5, RSA_SSA_PSS — схеме RSA-PSS. Вторая требует поддержки конкретного механизма провайдером или CNG. Нельзя менять алгоритм только в прикладной конфигурации без проверки сертификата, ключа, HSM и валидатора получателя. Контрольный PDF подписывают каждым разрешённым сочетанием и проверяют на чистом клиенте.

Поддержка эллиптических ключей также зависит от криптопровайдера. Сам факт наличия сертификата ECDSA в хранилище не гарантирует, что выбранный путь доступа к ключу реализует нужный механизм. При миграции с RSA на EC сначала проверяют подпись, временную отметку, построение цепочки и долгосрочную валидацию. Ошибка алгоритма не должна приводить к автоматическому выбору первого другого сертификата: это может сменить подписанта.

В отчёте о подписи сохраняют фактический хэш- и signature-алгоритм, а не только ожидаемую настройку. Это позволяет обнаружить отклонение провайдера или устаревший профиль. Политика проверки может отклонять подпись с запрещённым SHA-1 даже при математически корректном дайджесте. Такие правила применяют по дате подписания и назначению документа, чтобы исторический архив не оценивался тем же набором требований, что новая операция.

Программная проверка и дополнение существующих подписей

GetSignature возвращает объект существующей подписи, а ValidateSignature выполняет её проверку. Перед обходом получают количество подписей и обрабатывают каждую отдельно. Индекс в массиве не является постоянным бизнес-идентификатором: для отчёта используют имя поля, ревизию, сертификат и время. Если одна подпись не проходит проверку, остальные всё равно анализируют, чтобы показать полную картину документа.

AddValidationInformation добавляет сведения, необходимые для дальнейшей проверки существующей подписи. Это полезно, когда первоначальный провайдер не встроил OCSP или CRL либо документ нужно довести до LT-профиля. Метод не исправляет повреждённую подпись и не заменяет отсутствующий закрытый ключ. Сначала ValidateSignature должен подтвердить целостность и пригодность исходной подписи; затем получают цепочку и ответы статуса, записывают новую ревизию и снова валидируют результат.

Дополнение LTV изменяет документ инкрементально, но не меняет подписанные байты прежней ревизии. В DSS размещаются сертификаты и данные отзыва, а для LTA добавляется новая документная отметка времени. При продлении архивной подписи процесс повторяется до истечения применимых алгоритмов и доказательств. Планировщик должен знать дату следующего продления и не ждать момента, когда TSA или сертификат уже нельзя проверить.

ValidateSignature может вернуть криптографическую ошибку digest mismatch, если подписанные байты были изменены. Такой результат нельзя исправить повторным запросом OCSP или установкой корня. Нужно сохранить документ как доказательство, определить ревизию и причину изменения. Если подпись математически верна, но цепочка недоверенная, проблема относится к политике доверия и набору сертификатов — это другой статус и другое действие оператора.

Лицензия и проверка тестового результата

Функции подписи и штампа относятся к отдельным лицензионным возможностям. Перед запуском процесса проверяют, что ключ разрешает нужную операцию, иначе рабочий код может открывать PDF, но завершаться отказом при добавлении подписи или штампа. Лицензионный ключ устанавливают централизованно до создания очереди заданий; попытка подставлять его для каждого файла усложняет диагностику и может вызвать конкуренцию между потоками.

При ознакомительном режиме в выходные документы автоматически добавляется водяной знак. Такой файл нельзя выдавать клиенту или использовать как юридически значимый результат, даже если подпись технически сформирована. Приёмочный тест должен явно искать оценочную отметку и завершаться неуспехом при её наличии. После установки рабочего ключа контрольный PDF создают заново; удалять водяной знак редактором нельзя, поскольку это меняет документ и подписи.

Проблему лицензии отличают от ошибки сертификата. Если отказ повторяется для шифрования, подписи и штампа одинаково, проверяют ключ и его доступность процессу. Если шифрование работает, а AddSignature или AddStamps нет, сверяют разрешённые функции. Сообщение и код записывают вместе с идентификатором узла, чтобы не искать ошибку в PDF, когда один сервер фермы остался без корректной конфигурации.

Рабочий мониторинг должен периодически выполнять малый синтетический тест: открыть эталонный PDF, добавить невидимую или тестовую подпись в изолированном контуре, проверить результат и удалить его по политике. Такой тест обнаруживает истечение сертификата, потерю лицензии, недоступность HSM, TSA, OCSP, шрифтов и каталога кэша раньше, чем поступит пользовательский документ.

Особенности Windows, Linux и macOS

На Windows чаще всего возникают вопросы разрядности, хранилища сертификатов и профиля службы. Управляемая сборка может загружаться успешно, а нативная — нет. Сертификат виден интерактивному администратору, но отсутствует у сервисной учётной записи. Шрифт установлен только для текущего пользователя. Диагностический скрипт должен запускаться под реальной учётной записью процесса и проверять все четыре компонента: библиотеку, ключ, шрифт и каталоги.

На Linux нативная библиотека должна находиться в стандартном пути загрузчика либо в каталоге, добавленном до старта процесса. Если отсутствует требуемая GNU-библиотека, загрузчик сообщает о зависимом модуле, хотя основной файл существует. Для контейнера базовый образ выбирают с совместимой libc, затем проверяют зависимости командой системного загрузчика. Символические ссылки создают внутри образа осознанно, а не на хосте.

В Java на Linux и macOS имя и расширение нативной библиотеки должны соответствовать правилам JNI. Путь задают через java.library.path или загрузку абсолютного файла до первого обращения к классу. Изменение свойства после инициализации класса может не сработать, поскольку JVM уже закэшировала поиск. Ошибку UnsatisfiedLinkError анализируют вместе с архитектурой JVM и списком зависимостей.

На macOS процесс службы или приложения может иметь ограниченный доступ к каталогу и связке ключей. Сертификат и закрытый ключ должны быть доступны конкретному контексту запуска, а бинарные файлы — соответствовать требованиям подписи кода и архитектуре. Тест из терминала под владельцем проекта не заменяет запуск тем способом, которым приложение стартует после перезагрузки.

Координаты, страницы и устойчивые шаблоны

Номер страницы для подписи или штампа проверяют относительно нумерации интерфейса. Ошибка на единицу особенно опасна в документах, где титульный лист добавляется динамически. Перед применением шаблона приложение получает фактическое число страниц и убеждается, что целевая страница существует. Для правила последняя страница индекс вычисляют после всех операций объединения и вставки.

Размер страницы измеряется в пунктах PDF, где 72 пункта соответствуют дюйму. Координаты из HTML-предпросмотра пересчитывают по коэффициенту масштаба и с учётом того, что экран часто считает начало в левом верхнем углу, а PDF — в левом нижнем. Поворот страницы меняет визуальное положение. Универсальная функция преобразования должна принимать CropBox и Rotate, а её тесты — координаты четырёх углов.

Шаблон подписи не должен полагаться на свободное место фиксированного размера во всех документах. Для счетов и актов область определяют по типу формы, а для произвольного PDF — по якорю, найденному предыдущим этапом распознавания или компоновки. Если область занята, процесс должен выбрать другую страницу либо остановиться, а не накрыть сумму или реквизиты.

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

Архивирование и повторная проверка

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

Периодическая повторная проверка обнаруживает отзыв сертификата, изменение доверенной политики и приближение срока продления LTA. Результат не должен переписывать прежний отчёт: каждый запуск создаёт новую запись с датой и набором доверенных корней. Так видно, что подпись была действительна при приёме, даже если позднее политика изменилась.

Продление LTA планируют до истечения последней архивной отметки и до ослабления используемого алгоритма. Процесс получает существующие подписи, проверяет их, дополняет DSS актуальными доказательствами и добавляет новую временную подпись. После этого независимый валидатор подтверждает всю цепочку архивных отметок. Ошибка продления не должна изменять хранящийся оригинал; результат записывается как новая проверенная копия.

Если документ защищён паролем для доставки, архивная копия и транспортная копия могут иметь разные требования. Архивный PDF/A обычно не шифруют, а доступ контролируют хранилищем. Транспортный экземпляр можно защитить пользовательским паролем, но его пересохранение после подписи требует отдельного анализа. Наиболее предсказуемая схема формирует архивный подписанный оригинал и защищает канал или внешний контейнер, не меняя его байты.

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

Основные затраты зависят от размера PDF, числа объектов, сложности подписей и сетевых запросов. Шифрование и хэширование масштабируются по объёму файла, визуальный штамп — по числу страниц, а LT-подпись добавляет обращения к TSA и службам отзыва. Поэтому среднее время одного маленького тестового файла плохо прогнозирует очередь из сканов на сотни мегабайт.

Параллелизм ограничивают отдельно для CPU, памяти, диска, HSM и внешних служб. Четыре потока могут ускорить хэширование, но один токен всё равно выполнит операции последовательно. Большое число одновременных OCSP-запросов может вызвать ограничение со стороны центра сертификации. Практичная схема использует очередь, семафор для криптопровайдера и общий кэш валидных ответов.

Каждое задание получает тайм-аут, но принудительное завершение процесса во время SaveAs может оставить частичный файл. Результат сначала пишут во временное имя, затем проверяют и переименовывают. При повторном запуске система определяет, завершён ли документ по хэшу и журналу, а не только по наличию файла.

Метрики разделяют этапы: ожидание очереди, Open, добавление штампа, доступ к ключу, TSA, OCSP, SaveAs и валидацию. Тогда видно, где возникла деградация. В логах агрегируют коды ошибок и размеры, но не содержимое и пароли. Для ёмкостного планирования используют процентили, потому что редкие большие документы определяют необходимый запас памяти и тайм-аут.

Контроль качества перед вводом в эксплуатацию

  • Проверить незашифрованный PDF, файл только с паролем владельца и файл с пользовательским паролем.
  • Проверить каждый реально используемый набор разрешений в двух независимых просмотрщиках.
  • Подписать сертификатом из системного хранилища, программного файла, токена или HSM — только теми способами, которые применяются в производстве.
  • Смоделировать недоступность TSA, OCSP, CRL и прокси и убедиться, что профиль подписи не понижается молча.
  • Проверить кириллицу, длинные имена, альбомные и повёрнутые страницы в визуальном представлении подписи и штампе.
  • Проверить PAdES выбранного уровня независимым валидатором сразу после создания и после переноса на чистую машину.
  • Проверить DocMDP разрешёнными и запрещёнными изменениями, включая заполнение формы, вторую подпись и правку содержимого.
  • Проверить восстановление очереди после сбоя без повторной подписи уже завершённого документа.
  • Проверить права служебной учётной записи на нативные библиотеки, ключ, временный каталог, кэш и шрифты.
  • Убедиться, что trace, журналы и сообщения оператору не содержат пароли, PIN и секреты удалённых служб.

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

Сравнение 3-Heights PDF Security с аналогами

ПрограммаЛучше подходит дляГлавное ограничение
3-Heights PDF SecurityАвтоматического шифрования, PAdES-подписи, LTV, DocMDP и штампов в серверных процессахТребует программной интеграции и настройки сертификатов
PDF CommanderРучного редактирования, установки пароля и повседневной работы пользователя с PDFНе заменяет серверный API для квалифицированной массовой подписи
Adobe Acrobat ProИнтерактивной защиты, подписания, проверки и визуального редактирования документовРучной интерфейс менее удобен для высоконагруженной пакетной очереди
qpdfСкриптового шифрования, расшифрования и изменения параметров безопасностиНе создаёт цифровые подписи
iTextРазработки собственных PDF-процессов на Java и .NET с шифрованием и подписьюНужно учитывать AGPL либо коммерческую лицензию и писать больше прикладного кода
Apache PDFBoxОткрытых Java-проектов, где нужны базовые операции PDF, шифрование и программная подписьТребует самостоятельной сборки полного PAdES-процесса и инфраструктуры валидации

3-Heights PDF Security разумно выбирать, когда защита должна быть частью автоматизированного конвейера и важны PAdES, отметки времени, сведения об отзыве, аппаратные ключи и сохранение ревизий. PDF Commander удобнее человеку, которому нужно визуально исправить и защитить отдельный файл. Acrobat Pro подходит для интерактивной корпоративной работы и ручной проверки. qpdf хорош для паролей и разрешений без цифровой подписи. iText и PDFBox дают более широкую свободу разработки, но требуют самостоятельно собрать и протестировать больше компонентов криптографического процесса.

Как выбрать параметры для конкретной задачи

Для конфиденциальной отправки нужен пользовательский пароль; одни permission flags не закрывают содержимое. Для запрета правок без секретности достаточно пароля владельца и разрешений, но следует помнить, что недобросовестный просмотрщик может их игнорировать. Для доказательства автора нужна цифровая подпись. Для долгого хранения к ней добавляют доверенное время и данные отзыва. Для контролируемого последующего заполнения применяют DocMDP с подходящим уровнем разрешений.

Штамп выбирают, когда нужно показать служебную информацию на странице, но он сам по себе не подтверждает целостность. Если отметка должна быть защищена, она должна войти в подписанную ревизию. Шифрование выбирают для доступа, подпись — для целостности и происхождения, DocMDP — для политики изменений, PAdES-LT/LTA — для долгосрочной проверяемости. Эти механизмы решают разные задачи и не должны подменять друг друга.

Перед реализацией полезно оформить таблицу требований для каждого типа документа: кто открывает, кто может печатать и менять, кто подписывает, сколько лет хранится, разрешены ли последующие подписи, нужен ли видимый штамп, какие центры сертификации и TSA допускаются. Из этой таблицы прямо выводятся параметры SaveAs, свойства PdfSignature, DocMDP и правила валидации. Такой документ предотвращает случайный выбор настроек разработчиком.

Итоговый рабочий регламент

Надёжный процесс начинается с проверки входа и заканчивается независимой проверкой выхода. Между ними приложение открывает документ, применяет только заранее определённые операции, обращается к ключу и сетевым службам, сохраняет новый файл, читает коды ошибок и закрывает объекты. Секреты отделены от журналов, нативные библиотеки и шрифты развёрнуты для нужной архитектуры, а кэш имеет контролируемые права.

Для парольной защиты основным контрольным результатом является реальная невозможность открыть файл без пользовательского пароля и точное соблюдение разрешений. Для подписи — целостность, доверенная цепочка, время, отзыв и соответствие выбранному PAdES. Для штампа — правильная страница, координаты, шрифт и включение в нужную ревизию. Для DocMDP — реакция на каждое разрешённое и запрещённое изменение.

После настройки одного успешного примера процесс нельзя считать готовым. Его проверяют на разных размерах и вариантах PDF, при отказах сети и ключа, после перезапуска очереди и на чистой машине без пользовательского кэша. Только такой набор показывает, что защита воспроизводима, подпись проверяется у получателя, а сбой не приводит к выдаче частичного или более слабого документа.