Как реализовать пакетную подпись PDF-документов

5fd1f9d2096de287b2e3571ab4b86035.png

Автоматическое подписание документов электронной подписью используют там, где требуется пакетная подпись документов без участия сотрудника. Это могут быть как небольшие сайты, например по продаже билетов в театр и музей, или порталы с онлайн-обучением при отправке сертификатов о прохождении курсов, так и крупные банковские приложения, например, при генерации выписок по счетам, форм договоров или квитанций. В ЕСИА, СМЭВ, ГИС ЖКХ и других государственных информационных системах также реализована автоматическая подпись.

В этой статье реализуем автоматическое подписание для PDF-файлов и добавим штамп «Документ подписан электронной подписью».

Чтобы лучше понять, как же в PDF-файл добавляется электронная подпись, начнем статью со структуры файла. Далее упомянем архивные форматы, т.к. часто в ЭДО важно не только подписать, но и обеспечить длительное хранение. В пункте про электронные подписи покажем, как она встраивается в структуру файла и перечислим некоторые продукты с поддержкой PAdES на ГОСТ-алгоритмах. И, наконец, перейдем к основной теме статьи — пакетная подпись PDF. Если вам интересна отдельная часть, то переходите по заголовкам:

  • Что хранится внутри PDF-файла?

  • Как подготовить документ к архивному хранению?

  • Про электронные подписи в PDF

  • Пакетная подпись PDF

Что хранится внутри PDF-файла?

Если вы откроете PDF-файл обычным текстовым редактором, а не специальной программой, то увидите набор бессмысленных символов, редкие проблески читаемого текста и знакомые конструкции вроде »%PDF-» или »%%EOF». Какую-то очевидную логику и структуру в контенте проследить сходу сложно. 

PDF ориентирован на отображение документа в неизменном виде на любых устройствах. Он сохраняет точное форматирование, шрифты, изображения и макет, что особенно важно для печати и презентаций. Если тот же XML чаще используют для обмена данными между приложениями и сервисами, то PDF — для представления готовых документов, которые читают и обрабатывают люди. Спецификация формата ISO 32000–2 открыта. И хоть она не маленькая (почти тысяча страниц), попробуем выделить основное. 

PDF-файл состоит из следующих элементов:

Начальная структура PDF-файла
Начальная структура PDF-файла

Заголовок

Началом файла является заголовок. Это текстовая строка, из пяти символов »%PDF-» и номера версии (сейчас допустимы значения от %PDF–1.0 до %PDF–2.0)

Для указания ридерам, что после заголовка идут бинарные данные, после заголовка указывается строка с комментарием не менее 4 байт, где каждый байт должен быть равен или больше 128 (0×80). Это обеспечивает корректную обработку с определением типа документа (текстовый или бинарный).

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

Тело

Тело документа включает набор объектов, содержащих основной контент документа (изображения, текст и т.д.).

1 0 obj
% ...
endobj
2 0 obj
% ...
endobj

% ...

100 0 obj
% ...
endobj

Опишем восемь основных типов:

  1. Булево значение (Boolean): логические значения true или false.

  2. Число (Numeric): целое или вещественное число со знаком (опционально). Недесятичные основания или экспоненциальная запись не поддерживаются.
    Примеры: 42, 3.14, -67.7, +36,6. 

  3. Строка (String objects): текстовая строка длиной 0 и более байт. Строки оборачивают в круглые скобки (текстовая строка) или в треугольные (шестнадцатеричная строка). Текстовые строки могут записываться в несколько линий с переносом.
    Примеры: (Example), (), <4841425220544F5254>. 

  4. Имя (Name): начинается с символа / и используется для ключей. Содержит последовательность любых символов, кроме Null. Обычно не используются как текст для отображения.
    Примеры: /Type, /Name, /123.654.

  5. Массив (Array): Коллекция элементов различных типов, записанных в квадратных скобках. Поддерживаются только одномерные массивы, но допускается вкладывать одни массивы в другие с любой глубиной.
    Пример: [1 false (Example) 2.13].

  6. Словарь (Dictionary): пара «ключ-значение», заключенная в << и >>. Ключ должен быть представлен типом Name и быть уникальным в одном словаре. Значение может быть любого типа (в том числе другим словарем).
    Пример:  

    << /Key /Value
    /Subdictionary <<
    /Item0 (Example) /Item2 true
    >>
    >>

  7. Поток (Stream): последовательность байт любой длины, заключенных между stream и endstream, записанных после словаря. Например, поток может содержать текст, изображения или шрифты.

  8. Null: ключевое слово null, представляющее отсутствие значения. Если null используется как значение в словаре, то это соответствует пропуску записи.

Таблица перекрестных ссылок

Таблица перекрестных ссылок нужна для быстрого доступа к объектам в файле, обходясь без чтения всего файла.  Это похоже на «карту объекта» внутри PDF. Таблица представляет собой набор строк. Может быть в виде потока (stream).

Она состоит из записей формата:

nnnnnnnnnn ggggg  eol
  • Первые 10 символов: смещение объекта в байтах от начала документа.

  • Следующие 5 символов: номер поколения (или генерации).

  • Буква n или f: используется (n) или свободен (f).

  • eol — символ конца строки, должен быть представлен двумя символами.

Допускается два способа обозначения записей. Основной механизм использует связанный список: каждая свободная запись указывает на следующую, а первая запись (объект 0, головной) всегда свободна и имеет номер поколения 65 535, являясь началом списка. Последняя запись (хвост) ссылается обратно на объект 0.

Второй механизм позволяет другим свободным записям ссылаться на объект 0 с номером поколения 65 535, даже если они не входят в связанный список. Все объекты, кроме нулевого, изначально имеют номер поколения 0. При удалении объекта его запись помечается как свободная, добавляется в список, и ее номер поколения увеличивается на 1 для будущего использования. Максимальный номер поколения — 65 535; при его достижении запись больше не используется. Таблица должна содержать записи для всех номеров объектов от 0 до максимального, даже если некоторые объекты отсутствуют в файле.

xref
0 6
0000000001 65535 f
0000000018 00000 n
0000000091 00000 n
0000000000 00009 f
0000000321 00000 n
0000000543 00000 n

Пример: Таблица описывает 6 объектов, где с индексом 0 — удаленный, 1 — начинается с 18 байта, 2 — начинается с 91 байта, 3 — удаленный, 4 — начинается с 321 байта и 5 — начинается с 543 байта.

xref
0 1
0000000000 65535 f
2 1
0000011625 00000 n
13 2
0000025675 00002 n

25 1
0000026725 00000 n
32 1
0000025924 00000 n

Пример: Таблица содержит 5 объектов, где первый с индексом 0 — удаленный, с индексом 2 — начинается с 11625 байта, с индексом 13 — начинается с 25675 байта и имеет номер генерации равный 2, с индексом 25 — начинается с 264725 байта, с индексом 32 — начинается с 25924 байта.

Трейлер

Трейлер служит своеобразным «содержанием». Он помогает ридеру мгновенно найти нужные объекты и ускоряет открытие документа.

Трейлер используется, чтобы быстро находить таблицу ссылок и некоторые специальные объекты. PDF-документ читается с конца, где последняя строка должна включать маркер %%EOF. Перед ним идут две строки — startxref и смещение в байтах до начала таблицы ссылок. Перед startxref находится словарь трейлера.

Структура трейлера:

trailer 
  <<
    key1 value1
    key2 value2
    ...

    keyN valueN
  >>
startxref 
Byte_offset_of_last_cross-reference_section 
%%EOF 

Трейлер включает ключи:

  • /Size: количество записей в таблице.

  • /Prev: ссылка на предыдущий раздел перекрестных ссылок.

  • /Root: ссылка на корневой объект.

  • /Info: опционально, ссылка на метаданные документа.

Трейлер завершается ключевым словом startxref, за которым следует смещение кросс-референс таблицы.

Пример минимального файла

Рассмотрим следующий пример файла:

%PDF-2.0

1 0 obj

<< /Type /Catalog /Pages 2 0 R >>

endobj

2 0 obj

<< /Type /Pages /Kids [3 0 R] /Count 1 >>

endobj

3 0 obj

<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R >>

endobj

4 0 obj

<< /Length 44 >>

stream

BT

/F1 24 Tf

100 700 Td

(HABR) Tj

ET

endstream

endobj

xref

0 5

0000000000 65535 f 

0000000009 00000 n 

0000000056 00000 n 

0000000111 00000 n 

0000000219 00000 n 

trailer

<< /Size 5 /Root 1 0 R >>

startxref

478

%%EOF

Давайте разберем основные элементы этого файла:

  1. Заголовок %PDF-2.0 указывает, что файл соответствует версии 2.0.

  2. Объект 1 0 obj является корневым каталогом документа и содержит ссылку на объект 2 0 R, который описывает страницы.

  3. Объект 2 0 obj — это объект страниц, который ссылается на объект 3 0 R, представляющий первую страницу.

  4. Объект 3 0 obj описывает страницу, включая ее размеры (/MediaBox) и содержимое (/Contents 4 0 R).

  5. Объект 4 0 obj содержит поток данных (stream), включающий команды для отрисовки текста «Potato».

  6. Кросс-референс таблица (xref) указывает на смещения всех объектов в файле.

  7. Трейлер содержит информацию о корневом каталоге и размере таблицы.

Как вносятся изменения в PDF-файл?

Формат PDF позволяет вносить изменения в документ без полной перезаписи файла. Этот механизм называется инкрементальным обновлением (incremental update) и представляет собой процесс добавления новых данных в конец существующего файла. Вместо удаления старых данных новые объекты просто добавляются в конец файла, создается новая таблица перекрестных ссылок и обновляется трейлер. Такой подход не только экономит время при сохранении изменений, но и делает возможным редактирование в сценариях, когда перезапись исходного файла недоступна (например, при работе с документами через HTTP или OLE-встраивание в Windows).

По спецификации при инкрементном обновлении создается новая секция с изменениями, которая включает обновленные объекты, новую таблицу перекрестных ссылок (xref) и трейлер. При этом старые объекты не удаляются, а помечаются как неактивные.

Инкрементальное обновление PDF
Инкрементальное обновление PDF

Пример: если в документ добавляется новая аннотация, она записывается как новый объект, а затем обновляется страница, к которой она относится. В xref-таблице указываются смещения этих объектов в файле.

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

  7 0 obj<>

   endobj

Далее обновляется страница, к которой добавляется ссылка на аннотацию:

   3 0 obj<>

   endobj

Наконец, создается новая xref-таблица, которая указывает смещения новых объектов, и добавляется новый trailer:

   xref

   0 1

   0000000000 65535 f

   3 1

   0000000744 00000 n

   7 1

   0000000631 00000 n
trailer <>

Так выглядит указание на новую таблицу xref и завершение файла:

   startxref

   863

   %%EOF

После этих изменений файл будет содержать новую аннотацию, исходные данные останутся нетронутыми. А ридеры будут использовать самую последнюю версию объекта, указанную в последнем xref-индексе.

Как подготовить документ к архивному хранению?

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

Стандарт для архивного хранения

PDF/A — это подмножество формата PDF, созданное для обеспечения долговременного хранения электронных документов. Он исключает функции и возможности, которые могут затруднить или сделать невозможным доступ к файлу в будущем. Впервые архивный формат был стандартизирован как ISO 19005 в 2005 году.

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

Основные отличия PDF/A от стандартного PDF

PDF/A налагает ряд ограничений на использование функций стандартного PDF. Некоторые особенности:

  1. Встраивание шрифтов:

    Все шрифты, используемые в документе, должны быть встроены. Это предотвращает проблемы с отображением текста, если шрифт отсутствует на устройстве пользователя.

  2. Запрет шифрования:

    Не допускает шифрование или защиту паролем, так как это затрудняет доступ к документу в будущем.

  3. Однозначность цветов:

    Все цвета в документе должны быть описаны с использованием цветовых профилей, таких как sRGB или CMYK.

  4. Запрет внешних ссылок:

    Документ не должен ссылаться на внешние ресурсы, чтобы избежать потери данных при недоступности этих ресурсов.

  5. Метаданные:

    Требует обязательного использования метаданных в формате XMP (Extensible Metadata Platform).

  6. Поддержка только статического контента:

    Запрещено использование JavaScript, мультимедиа и других интерактивных элементов.

  7. Определенный порядок слоев и прозрачности:

    Для упрощения рендеринга в будущем все визуальные элементы должны быть однозначно упорядочены.

Уровни соответствия PDF/A

PDF/A состоит из нескольких частей, каждая из которых расширяет и уточняет стандарт:

  • PDF/A-1: базовый уровень (основан на PDF 1.4).

    Подходит для текстовых документов без сложных элементов вроде прозрачности.

  • PDF/A-2: поддержка новых функций (PDF 1.7).

    Добавлена прозрачность, сжатие JPEG 2000 и возможность объединять файлы в один PDF/A.

  • PDF/A-3: поддержка вложений.

    Позволяет встраивать произвольные файлы (например, XML или CSV) внутрь PDF/A.

Кроме того, PDF/A делится на уровни соответствия:

  • a (accessibility): требует полной доступности, включая семантические теги.

  • b (basic): гарантирует только визуальную целостность.

  • u (unicode): обеспечивает сохранение всех текстовых данных в Unicode.

Зачем использовать PDF/A?

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

  1. Юридические документы: Контракты, соглашения, судебные акты.

  2. Архивы организаций: Корпоративные отчеты, научные исследования, проекты.

  3. Государственные документы: Законы, постановления, исторические архивы.

  4. Медицинские записи: Истории болезней, результаты анализов.

Чем проверить соответствие PDF/A?

Для проверки документов на соответствие PDF/A используются специальные инструменты. Можно пользоваться встроенным в Adobe Acrobat. Если выбирать из opensource, то одним из наиболее надежных решений является veraPDF. Это бесплатное и открытое ПО, разработанное в рамках проекта Open Preservation Foundation и поддерживаемое Европейской комиссией.

Основные возможности veraPDF:

  • Проверка соответствия всем частям стандарта ISO 19005.

  • Отчеты о нарушениях в структуре PDF/A.

  • Поддержка командной строки для интеграции в автоматизированные процессы.

Пример: проверка PDF/A с помощью veraPDF и формированием отчета в html формате

verapdf.bat --format html "D:\Simple PDF 2.0 file.pdf" >> "D:\Simple PDF 2.0 file.report.html"

Инструмент анализирует файл, выявляет несоответствия и предлагает рекомендации по их устранению. Если документ соответствует стандарту, будет выведено подтверждение.

Результат проверки файла в veraPDF
Результат проверки файла в veraPDF

Какие регламенты по использованию PDF/A есть в России?

Федеральная налоговая служба (ФНС) Российской Федерации утвердила использование формата PDF/A-3 для подачи договорной документации в электронном виде. Данное решение зафиксировано в Приказе ФНС России от 24.03.2022 № ЕД-7–26/236@, который начал действовать спустя 30 дней после официальной публикации.

Формат PDF/A-3 был принят для обеспечения долгосрочного хранения электронных документов и их совместимости с различными программными платформами. PDF/A-3 позволяет объединить визуальное отображение документа (для удобства восприятия человеком) и структурированные данные в формате XML (для автоматизированной обработки). Это важно для договоров, соглашений, протоколов разногласий и других документов, требующих высокой точности и юридической значимости.

Ключевые характеристики формата:

  1. Единый файл-контейнер: содержится как визуальная часть (для чтения), так и вложенный XML-файл (для автоматической обработки).

  2. Электронная подпись: Документы заверяются электронной подписью, соответствующей требованиям Федерального закона № 63-ФЗ «Об электронной подписи».

  3. Универсальность: Формат поддерживает различные типы договорных документов, включая договоры, протоколы разногласий и дополнительные соглашения.

Про электронные подписи в PDF

Мы уже познакомились с базовой структурой файла и с инкрементальным обновлением, теперь рассмотрим как это использовать при добавлении подписи внутрь документа.

А зачем вообще использовать электронную подпись? ЭП обеспечивает:

  1. Проверку целостности документа — гарантия, что документ не изменялся после подписания.

  2. Подтверждение личность подписавшего с использованием инфраструктуры открытых ключей (PKI).

  3. Контроль изменений и ограничение разрешений после подписания.

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

PAdES (PDF Advanced Electronic Signatures) — это стандарт для создания и проверки электронных подписей в документах формата PDF. Он был разработан на основе спецификаций ETSI (European Telecommunications Standards Institute) и обеспечивает высокий уровень безопасности и юридической значимости подписей. PAdES поддерживает различные уровни подписей, включая долгосрочные, что позволяет гарантировать долговечность и достоверность подписанных документов даже спустя годы.

Типы подписей в PDF

Стандарт поддерживает два типа электронных подписей с использованием сертификатов :

  1. Заверяющая подпись или подпись для утверждения (Approval Signature):

    • Позволяет многократное подписание.

    • Может использоваться для заполнения форм.

  2. Сертифицирующая подпись (Certification Signature):

    • Должна быть одна в документе и при этом ставится первой.

    • Ограничивает дальнейшие изменения (например, разрешая только аннотации или добавление подписей).

    • Может быть как видимой, так и без отображения на странице.

Основная структура подписей в PDF

Электронная подпись в PDF хранится в специальной структуре, называемой словарем подписей (Signature Dictionary). Эта структура содержит метаданные подписи и ссылки на связанные данные:

  • Ключ /Contents: хранит значение подписи — закодированный объект PKCS#7, включающий хеш документа, зашифрованный закрытым ключом подписанта.

  • Ключ /ByteRange: указывает, какие байты документа были включены в хеш при создании подписи. Это массив из четырех чисел, определяющий диапазоны данных (до и после области, зарезервированной для подписи).

  • Ключ /Filter: указывает, какой обработчик подписей использовался.

  • Ключ /SubFilter: уточняет формат и алгоритм подписи.

Пример структуры подписей:

  /Type /Sig
  /Filter /Adobe.PPKLite - Используемый метод подписи 
  /SubFilter /adbe.pkcs7.detached - Формат подписи
  /ByteRange [0 840 960 240] - Диапазон для хеширования
  /Contents <...> Поле для самой подписи (резервируем место)
  /Reason (Approval of contract) - Причина подписи (опционально)
  /M (D:20250128120000Z) - Дата подписи
  /ContactInfo (support@example.com)

Процесс создания подписи

Добавление электронной подписи состоит из нескольких этапов:

  1. Новая секция обновления добавляется в документ (то самое инкрементальное обновление).

  2. Добавляем изображение в документ для XObject Form связанного с подписью (если требуется визуализация).

  3. Резервируем пространство и выполняем промежуточное сохранение документа перед подписанием

    1. Резервируем пространство в поле Contents. Значение этого поля не может быть меньше значения подписи, поэтому выделяем с запасом (неиспользуемая часть будет заполнена нулями).

    2. Так как мы не знаем, где окажется Contents после сохранения, то нам потребуется также зарезервировать пространство для ByteRange.

      Массив /ByteRange состоит из четырех чисел. Первое число в каждой паре — это смещение (от начала, начиная с 0) начала потока байтов, которые должны быть включены в хэш. Второе число — это длина этого потока. Две пары определяют две последовательности байтов, которые определяют, что должно быть хэшировано.

    Перед подписанием ByteRange имеет вид: /ByteRange [          0          0          0          0]

    3. После сохранения нужно определить начало и конец содержимого Contents (значением между < >) и обновить значения для ByteRange.

    /ByteRange [          0       3291       7935       4218]

  4. Получим подписываемый контент с использованием имеющихся значений ByteRange.

  5. Вызываем подпись полученного контента с помощью обработчика (отдельного модуля).

  6. Сохраняем полученную подпись в поле Contents.

    Пример готовой структуры Contents: /Contents <3082025B06092A864886F70D010702A082024C30820248...>

Подписываемые данные и встраивание подписи внутрь PDF
Подписываемые данные и встраивание подписи внутрь PDF

Продукты и сервисы с поддержкой PAdES на ГОСТах

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

Продукты

КриптоАРМ — это решение для работы с электронной подписью и шифрованием данных, включая подписание PDF-документов. Продукт поддерживает различные форматы подписей, включая CAdES и PAdES по ГОСТам. Можно подписывать документы встроенной, присоединенной или отсоединенной подписью на выбор. Есть сертификация pdf документа, можно разметить несколько областей для подписания, конвертировать в архивный формат. Есть поддержка разных ОС (Windows, Linux, macOS). В режиме пакетной подписи может подписать файлы любого формата. Реализована визуализация электронной подписи — добавление изображения штампа подписи. Для серверного использования, под автоматизацию, есть отдельное исполнение — КриптоАРМ Server.

КриптоПро PDF — это модуль для Adobe Acrobat и Reader, предназначенный для создания и проверки электронных подписей на ГОСТ-алгоритмах. Гибкая настройка внешнего вида штампа. Есть пакетная подпись (только в Adobe Acrobat Standard или Adobe Acrobat Pro). Работает только на Windows.

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

CryptExpert — это программное обеспечение для создания и проверки электронных подписей. В CryptExpert можно подписывать PDF-файлы как встроенной подписью, так и в виде отдельного файла.

Окуляр ГОСТ — приложение создано на основе свободного приложения Okular. Дополнено поддержкой ЭП (использует КриптоПро). Работает на Windows и Linux.

Сервисы

sign.kloud.one — это сервис для проверки электронных подписей, в том числе и стандарта PAdES.Для PDF-документов после проверки доступна возможность скачать копию файла с визуальным штампом о сведениях подписи. Интересная опция: возможность улучшить стандарт подписи. Исходный код открыт и доступен по ссылке.

КриптоПро SVS 2.0 — это программно аппаратный комплекс для проверки сертификатов и электронных подписей. Решение позволяет проверять подписи, созданные с использованием различных стандартов, таких как CAdES, XAdES и PAdES, а также поддерживает проверку сертификатов на соответствие требованиям регулятора.

Миг24 — это сервис для формирования разных видов подписей (открепленная подпись, прикрепленная подпись, встроенная). Решение поддерживает стандарты ГОСТ. Есть возможность визуализировать подпись.

Пакетная подпись PDF

После знакомства со структурой файла и основами PAdES переходим к практической части — настройке автоматической подписи документов на сервере.

Чтобы не подписывать некую сову, предположим, что мы — бюро кредитных историй (это не так, все совпадения случайны). На Госуслугах начала работать услуга по самозапрету кредитования. Наша задача — отправить клиенту решение в читаемом виде и подписанное УКЭП. Собравшись и обсудив задачу с командой, принято решение — не отправлять PDF с картинкой про подпись, а использовать PAdES.

Т.к. для подписания нам в любом случае потребуется сертификат, необходимо его получить. И нам, как БКИ, стоит обратиться с этим в УЦ Центрального Банка. Сертификат нам выдали, но в сведениях о субъекте там нет ни имени руководителя, ни хотя бы сотрудника. Ошибка? Нет! Это так называемый обезличенный сертификат, который и нужен для автоматического подписания на сервере.

Что такое обезличенная электронная подпись?

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

В России обезличенные сертификаты для информационных систем выдаются несколькими государственными структурами:

  • ФНС России выпускает квалифицированные сертификаты операторам информационных систем.

  • Центробанк РФ выпускает такие сертификаты для организаций, работающих в рамках ч. 1 ст. 76.1 Закона о Центральном банке.

  • Федеральное казначейство выдает сертификаты для органов государственной власти.

Примеры кода по автоматизации подписи PDF

Следующий шаг нашей команды за аналитиками и разработкой. Они подбирают подходящее решение для пакетной подписи PDF. Из условий: модуль можно использовать в node.js и упаковать всё решение в микросервис, а подпись конечно должна быть реализована на ГОСТ-алгоритмах. В качестве подходящего варианта для работы со структурой файла, решили остановится на модуле с открытым кодом — trusted-pdf (из состава КриптоАРМ Server, о нем упоминали ранее в списке продуктов).

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

Для простоты тут приведем псевдокод реализации (если будет интересно, напишите, выложим полные примеры):

Добавление невидимой подписи

import * as fs from "node:fs";
import * as pdf from "@trusted-pdf/pdf";
import * as pdfSign from "@trusted-pdf/sign";

const buf = fs.readFileSync(path/Simple PDF 2.0 file.pdf);
const doc = new pdf.Document();

doc.read(buf);

const sign = new pdfSign.Sign(doc);

sign.addSignatures({
  name: "signature 1",
  page: 1,
});

doc.save();

Добавление подписи со штампом

import * as fs from "node:fs";
import * as pdf from "@trusted-pdf/pdf";
import * as pdfSign from "@trusted-pdf/sign";

const buf = fs.readFileSync(path/to/input.pdf);
const doc = new pdf.Document();

doc.read(buf);

const sign = new pdfSign.Sign(doc);

sign.addSignatures({
  name: "signature 1",
  page: 1,
  rectangle: {
	x: 20,
	y: 750,
	height: 150,
	width: 50,
  },

  stream: Buffer.from("0.5 g\n0 0 150 50 re\nf"),
});

doc.save();

Подписание внешним модулем

import * as fs from "node:fs";
import * as pdf from "@trusted-pdf/pdf";
import * as pdfSign from "@trusted-pdf/sign";

const buf = fs.readFileSync(path/to/input.pdf);

const doc = new pdf.Document();

doc.read(buf);

const sign = new pdfSign.Sign(doc);
const sig = sign.getSignature("signature 1");

await sig.sign({
  contentLength: 1300,
  onUpdate: async () => {
	sig.dict
    	.get("V", PdfDictionary)
    	.set("Name", doc.createLiteral("Иванов И.И."));
  },

  onSign: async (content) => {

	// Подписание Content и формирование блока подписи в формате CMS
    // Выполняется в отдельном модуле

	return new Uint8Array(cms);
  },
});

doc.save();

Результат проверим в некоторых упомянутых ранее продуктах и сервисах:

Результат проверки на тестовом сервисе КриптоПро SVS
Результат проверки на тестовом сервисе КриптоПро SVS
Проверка подписанного PDF-файла в КриптоАРМ
Проверка подписанного PDF-файла в КриптоАРМ

Вывод

Формат PDF — это не просто удобный способ представления документов для чтения или печати, но и хороший инструмент для интеграции с системами электронного документооборота, архивного хранения и электронной подписи.

Мы рассмотрели основные элементы PDF-файла, требования архивного стандарта и возможности использования ГОСТ-алгоритмов для подписи документов (с примерами продуктов и сервисов). Надеемся, что представленные материалы помогут вам глубже понять формат и успешно применять его в ваших проектах.

P.S. Если какую-то тему стоит раскрыть подробно отдельно, пишите в комментариях.

© Habrahabr.ru