Перейти к содержимому

Сценарий подписанных соглашений

Spec: ETSI EN 319 142-2, §5.1 Spec: ISO 32000-2:2020, §12.8 Evidence: Mixed evidence

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

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

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

  • Сначала подготовка, потом подпись. Подпись покрывает ровно тот диапазон байтов, по которому она была вычислена. Считайте документ окончательным — включая любые позднее присоединённые редакции — до подписания, а не после.
  • Выбирайте уровень под обязательство, а не наоборот. PAdES задаёт градацию: базовая подпись, подпись с меткой времени, подпись со встроенным материалом для проверки и подпись, повторно проштампованная для бессрочной архивной действительности (ETSI EN 319 142-2 §5.1).
  • Долгосрочная действительность — это структура, а не свойство. Это хранилище безопасности документа (Document Security Store) плюс метка времени документа, записанные в файл (ISO 32000-2:2020 §12.8).
  • Точно называйте шов. Высокоуровневый NextPDF Document::setSignature() замораживает публичный API, но сразу завершается ошибкой, а не выдаёт неподписанный файл. Реализованный путь — это низкоуровневый оркестратор. На этой странице мы не делаем вид, что это не так.

NextPDF разделяет решение и механизм. Решение — это то, какой уровень PAdES нужен для обязательства. Механизм — это то, как подписываются байты и как переносится материал для проверки. Если относиться к ним как к одному целому, команда получает подпись, которая действительна, но недолговечна.

У этого сценария четыре этапа.

  1. Prepare the document Compose the agreement and treat it as final. The signature will protect this exact byte range and nothing added outside it without a new revision.
  2. Choose the obligation B-B proves who. B-T adds trusted time. B-LT embeds the material to validate later. B-LTA re-stamps for indefinite validity.
  3. Sign A CMS signature is embedded in the signature dictionary over the byte range; a timestamp is requested from a TSA if the level needs one.
  4. Preserve For long-term levels, the Document Security Store and a document timestamp are written so the signature outlives its certificate.
Сценарий подписанного соглашения от начала до конца: каждый этап добавляет гарантию, а уровень, выбранный на втором этапе, определяет, сколько свидетельств должны произвести третий и четвёртый этапы.

Перечисление уровней существует в коде и прямо кодирует обязательство. B-B подтверждает личность подписанта. B-T добавляет доверенную метку времени. “Когда” проверяется так же строго, как “кто”. B-LT встраивает сертификаты и ответы об отзыве, необходимые для проверки подписи после истечения срока действия сертификата подписи. B-LTA добавляет метки времени документа, чтобы цепочку доверия можно было продлевать бессрочно, повторно проставляя штамп перед истечением срока действия каждого сертификата метки времени. Это перечисление фиксирует, какие уровни требуют метки времени, а какие — встроенного материала для проверки, поэтому движок может отклонить невозможную комбинацию, а не создавать вводящий в заблуждение “подписанный” файл.

Эта градация подкреплена стандартом. Evidence: Standard-backed Spec: ETSI EN 319 142-2, §5.1 описывает уровни PAdES как надстройку над строительными блоками EN 319 142-1, начиная с базовой встроенной подписи и выше. Структура долгосрочной проверки зафиксирована стандартом Spec: ISO 32000-2:2020, §12.8 : долгосрочная проверка опирается на хранилище безопасности документа (Document Security Store) и словарь метки времени документа, записанные в файл.

Модель уровней подкреплена кодом. Evidence: Code-backed Перечисление SignatureLevel содержит четыре варианта PAdES (B-B, B-T, B-LT, B-LTA) с методами-предикатами “требует метку времени”, “требует встроенный материал для проверки” и “требует метки времени документа”. Высокоуровневый Document::setSignature() снабжён защитой с мгновенным отказом, которая выдаёт блокирующую диагностику, по которой можно действовать, а не неподписанный документ — это проверяемое поведение, а не утверждение.

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

Здесь показано решение — выбор обязательства — с использованием реального перечисления. Реализованный путь подписания — это низкоуровневый оркестратор. Высокоуровневый вызов показан только для того, чтобы явно продемонстрировать поведение с мгновенным отказом.

<?php
declare(strict_types=1);
use NextPDF\Security\Signature\SignatureLevel;
/**
* Map a business obligation to a PAdES level.
*
* The obligation drives the level, not the reverse — choosing B-B for a
* 10-year contract is a decision you do not want to make implicitly.
*/
function levelForObligation(string $obligation): SignatureLevel
{
return match ($obligation) {
// Internal sign-off, short retention, signer identity is enough.
'internal_approval' => SignatureLevel::PAdES_B_B,
// Counterparty agreement: prove the moment of signing.
'counterparty_agreement' => SignatureLevel::PAdES_B_T,
// Regulated contract that must verify after cert expiry.
'regulated_contract' => SignatureLevel::PAdES_B_LT,
// Long-lived legal record: indefinite, re-stampable validity.
'long_term_legal_record' => SignatureLevel::PAdES_B_LTA,
default => throw new \InvalidArgumentException(
"Unknown obligation: {$obligation}",
),
};
}
$level = levelForObligation('regulated_contract');
// The enum carries the obligation's implications with it.
$needsTsa = $level->requiresTimestamp(); // true for B-T+
$needsDss = $level->requiresDss(); // true for B-LT+
$needsArchive = $level->requiresDocumentTimestamp(); // true only for B-LTA

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

Частое заблуждение — “подпись действительна, значит, мы закончили.” Действительность сегодня необходима, но недостаточна. Подпись вычисляется по диапазону байтов. Всё, что присоединено за пределами этого диапазона в более поздней редакции, ею не покрывается — именно поэтому подготовка должна идти перед подписанием. А подпись, которая проходит проверку сейчас, может дать сбой позднее, когда истечёт срок действия её сертификата, если только материал для проверки не был встроен во время подписания. “Действительная” и “долговечная” — это разные гарантии, и только обязательство подсказывает, какая из них вам действительно нужна.

Ещё одна ловушка, специфичная для этого движка: предположение, что высокоуровневый setSignature() уже сегодня создаёт подписанный файл. Это не так. Он намеренно завершается мгновенным отказом. Относитесь к диагностике как к контракту.

  • Document::setSignature() — это замороженная публичная поверхность, а не реализованный механизм подписания. Он завершается мгновенным отказом с блокирующей диагностикой. Он никогда не выдаёт неподписанный PDF вместо подписанного. Реализованный путь — это низкоуровневый двухфазный оркестратор.
  • Долгосрочное сопровождение проверки (DSS/VRI, контроль состояния, цикл архивных меток времени) — это возможность уровня Premium. Core не предоставляет цикл архивирования. См. границу ниже.
  • Подпись защищает ровно свой диапазон байтов. Позднее присоединённые редакции отделены от неё. Движок не расширяет покрытие задним числом.
  • NextPDF создаёт и сопровождает структуры; он не выносит решений. Является ли подпись доверенной, зависит от якорей доверия и политики проверяющей стороны, которые находятся за пределами движка.
  • B-LTA сам по себе не делает подпись вечной. Он обеспечивает бессрочную действительность только при условии, что цикл повторного штампования выполняется по расписанию до истечения срока действия каждого сертификата метки времени.
  • Эта страница описывает архивную поверхность Premium на уровне поведения. Она не утверждает признание каким-либо конкретным судом или органом.
Подписание PAdES и долгосрочная действительность — edition availability
Edition Availability
Core

Core предоставляет перечисление SignatureLevel и замороженную поверхность Document::setSignature() (мгновенный отказ). Реализованный низкоуровневый оркестратор покрывает базовое подписание. Долгосрочное архивное сопровождение в Core отсутствует.

Pro

Базовое подписание PAdES (B-B / B-T) через оркестратор доступно.

Enterprise

Добавляет B-LT / B-LTA, хранилище безопасности документа (Document Security Store), сопровождение VRI для каждой подписи, контроль состояния LTV и цикл архивных меток времени документа для бессрочной действительности.

  • PAdES — PDF Advanced Electronic Signatures: семейство профилей ETSI, определяющее, как усовершенствованная электронная подпись переносится в PDF.
  • Диапазон байтов — непрерывный участок байтов файла, по которому вычисляется подпись; содержимое за его пределами этой подписью не защищено.
  • Уровень подписи (B-B / B-T / B-LT / B-LTA) — градация PAdES: кто подписал, когда, со встроенным материалом для проверки и с возможностью повторного штампования для бессрочной архивной действительности.
  • TSA — Time-Stamping Authority (служба меток времени): служба RFC 3161, которая удостоверяет, что определённое состояние документа существовало в заданный момент времени UTC.
  • DSS (Document Security Store) — внутрифайловое хранилище сертификатов, ответов OCSP и CRL, необходимых для проверки подписи после истечения срока действия её сертификата.
  • LTV (Long-Term Validation) — поддержание проверяемости подписи с течением времени за счёт встраивания свидетельств для проверки и повторного штампования.
  • Fail-fast (мгновенный отказ) — отказ создавать вводящий в заблуждение артефакт и выдача вместо этого ошибки, по которой можно действовать, а не выпуск тихо неверного файла.