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

Устранение неполадок: ошибки подписи и метки времени

В этих записях описаны сбои подписи, которые проявляются как NextPDF\Exception\SignatureException и NextPDF\Security\Signature\Exception\SignatureLevelUnreachableException. Каждая запись указывает точный фабричный метод или класс, поэтому вы можете подтвердить причину по сообщению и getContext(), а не строить догадки.

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

Запись: уровень PAdES “B-LT” или “B-LTA” не может быть создан

Заголовок раздела «Запись: уровень PAdES “B-LT” или “B-LTA” не может быть создан»
  • Симптом. SignatureException с окончанием сообщения nextpdf/enterprise package is required for B-LT/B-LTA signatures.
  • Вероятная причина. Отсутствует поставщик возможностей долгосрочной проверки. B-LT и B-LTA встраивают данные об отзыве и архивную метку времени; этот поставщик входит в nextpdf/enterprise.
  • Свидетельство / диагностика. Фабричный метод SignatureException::ltvCapabilityMissing() генерирует именно это сообщение. getContext() возвращает signature_level со значением уровня, который вы пытались задать.
  • Решение.
    1. Установите поставщик, выполнив composer require nextpdf/enterprise.
    2. Повторите вызов подписания.
    3. Если установить поставщик нельзя, запросите вместо этого B-B или B-T, которые может создать пакет core.
  • См. также. Справочник по исключениям.

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

Заголовок раздела «Запись: уровень подписи недостижим, и вызов отклоняется»
  • Симптом. SignatureLevelUnreachableException с сообщением в форме PAdES level "<x>" is unreachable (highest achievable: "<y>").
  • Вероятная причина. Запрошенный уровень соответствия требует инфраструктуру, недоступную во время подписания, чаще всего службу меток времени для B-T и выше. Движок завершает операцию отказом: не понижает уровень молча и не заявляет более высокий уровень.
  • Свидетельство / диагностика. getContext() возвращает requestedLevel, highestAchievableLevel и reason. Поле reason указывает, какой инфраструктуры не хватает. Это поведение по умолчанию с завершением при отказе: оно не допускает выпуск документа с заявленным уровнем, которому документ не соответствует.
  • Решение.
    1. Проверьте поле reason, чтобы определить отсутствующую инфраструктуру.
    2. Подключите отсутствующий компонент. Например, настройте службу меток времени и снова выполните вызов.
    3. Если нужно намеренно принять более низкий уровень, передайте allowDegradation: true в PadesOrchestrator. Тогда вызов создаст highestAchievableLevel и сообщит созданный уровень.
  • См. также. Шифрование и разрешения.

Запись: требуется клиент службы меток времени, но он отсутствует

Заголовок раздела «Запись: требуется клиент службы меток времени, но он отсутствует»
  • Симптом. SignatureException с окончанием TSA client is required for level <x> but none was provided.
  • Вероятная причина. Для запроса B-T, B-LT или B-LTA нужен клиент службы меток времени, а у оркестратора его нет.
  • Свидетельство / диагностика. Фабричный метод SignatureException::tsaRequired() генерирует это сообщение; getContext() содержит запрошенный signature_level.
  • Решение.
    1. Настройте клиент службы меток времени и передайте его оркестратору.
    2. Повторите вызов.
    3. Чтобы создать уровень, не требующий метки времени, запросите B-B.
  • См. также. Справочник по исключениям.

Запись: URL-адрес конечной точки службы меток времени пуст

Заголовок раздела «Запись: URL-адрес конечной точки службы меток времени пуст»
  • Симптом. SignatureException с окончанием TSA endpoint URL is empty.
  • Вероятная причина. Клиент службы меток времени был создан с пустым URL-адресом конечной точки.
  • Свидетельство / диагностика. Фабричный метод SignatureException::tsaUrlEmpty() генерирует это сообщение. Это ошибка конфигурации, а не сетевой сбой.
  • Решение.
    1. Задайте на клиенте службы меток времени непустой URL-адрес конечной точки, например https://timestamp.example.com/tsa.
    2. Если для запрошенного уровня метка времени не нужна, вместо этого удалите привязку клиента службы меток времени.
    3. Повторите вызов.
  • См. также. Справочник по исключениям.

Запись: в буфере отсутствует заполнитель подписи

Заголовок раздела «Запись: в буфере отсутствует заполнитель подписи»
  • Симптом. SignatureException с окончанием no /Contents <…> field found in PDF buffer (signature placeholder missing).
  • Вероятная причина. Этап подписания получил буфер без зарезервированного контейнера подписи, поэтому ему некуда записать подпись.
  • Свидетельство / диагностика. Фабричный метод SignatureException::signatureContentsNotFound() генерирует это сообщение.
  • Решение.
    1. Убедитесь, что поле подписи и заполнитель для него записаны до запуска этапа подписания.
    2. Перезапустите конвейер, чтобы заполнитель существовал к моменту начала подписания.
  • См. также. Справочник по исключениям.

Запись: статус отзыва неизвестен (ответчик OCSP отклонил запрос)

Заголовок раздела «Запись: статус отзыва неизвестен (ответчик OCSP отклонил запрос)»
  • Симптом. SignatureException с окончанием OCSP responder returned non-successful OCSPResponseStatus "<status>".
  • Вероятная причина. Ответчик Online Certificate Status Protocol (OCSP) не вернул статус successful, поэтому не предоставил утверждение об отзыве. В исходном коде движок ссылается на RFC 6960 §4.2.1: заполненное тело ответа допускается только для статуса successful (0). Отклонённый ответ движок не считает положительным результатом с точки зрения доверия.
  • Свидетельство / диагностика. Фабричный метод SignatureException::nonSuccessfulOcspResponseStatus() генерирует это сообщение и указывает полученный статус, например tryLater или internalError. Если байт статуса зарезервирован или неизвестен, вместо этого срабатывает SignatureException::reservedOcspResponseStatus().
  • Решение.
    1. Посмотрите статус в сообщении. Для временного статуса вроде tryLater повторите запрос на получение данных об отзыве позже.
    2. Для unauthorized или malformedRequest проверьте URL-адрес запроса OCSP и сертификат, ожидаемый ответчиком.
    3. Не подавляйте сбой при получении артефакта B-LT или B-LTA; утверждение об отзыве является частью этого уровня.
  • См. также. Справочник по исключениям.

Запись: запись цепочки сертификатов не декодируется

Заголовок раздела «Запись: запись цепочки сертификатов не декодируется»
  • Симптом. SignatureException с окончанием failed to base64-decode PEM body — input is not valid PEM.
  • Вероятная причина. Запись цепочки сертификатов не соответствует корректному формату Privacy-Enhanced Mail (PEM), обычно из-за усечения, постороннего символа или двоичного блока Distinguished Encoding Rules (DER), переданного там, где ожидался PEM.
  • Свидетельство / диагностика. Фабричный метод SignatureException::pemDecodingFailed() генерирует это сообщение во время сборки цепочки.
  • Решение.
    1. Проверьте каждый сертификат цепочки на наличие посторонних символов или усечения.
    2. Повторно экспортируйте затронутый сертификат в формате PEM.
    3. Повторите вызов подписания.
  • См. также. Шифрование и разрешения.

Запись: тип закрытого ключа не соответствует алгоритму

Заголовок раздела «Запись: тип закрытого ключа не соответствует алгоритму»
  • Симптом. SignatureException с окончанием expected private key of type "<x>" for the configured algorithm but got "<y>".
  • Вероятная причина. Загруженный закрытый ключ не соответствует настроенному алгоритму подписи, например, ключ Rivest-Shamir-Adleman (RSA) при выборе Elliptic Curve Digital Signature Algorithm (ECDSA).
  • Свидетельство / диагностика. Фабричный метод SignatureException::unexpectedKeyType() генерирует это сообщение и указывает как ожидаемый, так и фактический класс ключа.
  • Решение.
    1. Убедитесь, что сертификат и пара ключей соответствуют выбранному алгоритму.
    2. Измените выбор алгоритма так, чтобы он соответствовал ключу, или загрузите ключ, соответствующий алгоритму.
    3. Повторите вызов подписания.
  • См. также. Справочник по исключениям.

Запись: ключ или материал подписи Ed25519 имеет неверный формат

Заголовок раздела «Запись: ключ или материал подписи Ed25519 имеет неверный формат»
  • Симптом. SignatureException с окончанием, указывающим на несоответствие длины Ed25519: например, Ed25519 signature length <n> ≠ expected 64 bytes или Ed25519 round-trip self-verify failed.
  • Вероятная причина. Криптографическая среда выполнения вернула ключ или материал подписи неверной длины, либо только что созданная подпись не проверяется собственным открытым ключом. В исходном коде движок ссылается на RFC 8032 §3.4, где длина отсоединённой подписи Ed25519 зафиксирована как 64 байта. Движок прерывает работу, а не выдаёт материал, который не может самостоятельно проверить.
  • Свидетельство / диагностика. Соответствующие фабричные методы: SignatureException::ed25519SignatureMalformed(), ::ed25519RoundTripVerifyFailed(), ::ed25519KeyParseFailed(), ::ed25519SeedInvalid(), ::ed25519SecretKeyMalformed() и ::ed25519PublicKeyInvalid(). Каждый указывает наблюдаемую длину.
  • Решение.
    1. Переустановите PHP-расширение libsodium; урезанная или повреждённая сборка задокументирована как причина появления материала неверной длины.
    2. Убедитесь, что ключ относится к Ed25519 и используется OpenSSL версии 1.1.1 или новее.
    3. Повторите вызов подписания.
  • См. также. Справочник по исключениям.

Запись: словарь архивной метки времени не был выведен

Заголовок раздела «Запись: словарь архивной метки времени не был выведен»
  • Симптом. SignatureException с окончанием no /Type /DocTimeStamp dictionary was emitted into the PDF buffer.
  • Вероятная причина. Архивный цикл B-LTA выполнился, но словарь метки времени документа так и не попал в буфер. Артефакт был бы недописанным B-LTA, поэтому движок отказывается его возвращать.
  • Свидетельство / диагностика. Фабричный метод SignatureException::documentTimestampNotEmitted() генерирует это сообщение. Это нарушение постусловия возникает на этапе финализации.
  • Решение.
    1. Считайте вывод отброшенным; не поставляйте частичный артефакт.
    2. Перезапустите конвейер B-LTA с доступной службой меток времени.
    3. Если сбой повторяется, зафиксируйте getContext() и связанное предыдущее исключение для отчёта о дефекте.
  • См. также. Справочник по исключениям.
  • Эти фабричные методы задают cert_info в виде субъекта или отпечатка только тогда, когда он доступен; пустое cert_info ожидаемо для сбоев возможностей и конфигурации.
  • Запрос B-LT или B-LTA без настроенного клиента Hypertext Transfer Protocol (HTTP) вызывает SignatureException::httpClientMissing(); для получения данных об отзыве оркестратору нужно передать клиент PHP Standards Recommendation (PSR)-18.
  • Сертификат, который опирается на аппаратный модуль безопасности (HSM), но не имеет реализации подписывающего компонента, вызывает SignatureException::hsmSignerMissing(); перед подписанием привяжите подписывающий компонент к сертификату.

Глоссарий: уровень PAdES · утверждение об отзыве