Enterprise редакция
Проверка подписи — глубокий справочник
Краткий обзор
Заголовок раздела «Краткий обзор»Эта страница — подробный справочник по поверхности проверки AdES в NextPDF Enterprise. Точка входа — NextPDF\Enterprise\Security\Validation\AdESValidationEngine. Он реализует смоделированные по ETSI процессы проверки NextPDF для базовых, временных, долгосрочных и архивных проверок меток времени: базовая проверка, проверка со временем, проверка с долгосрочными данными и проверка архивной цепочки покрытия DocTimeStamp. Результаты — значения ValidationReport, несущие варианты перечислений MainIndication и SubIndication со строковыми значениями URN ETSI. Дополнительные поверхности, описанные здесь: SPI SignatureDataExtractor и его реализация CmsSignatureDataExtractor, побайтовый сканер PdfSignatureDictionaryScanner, поверхность проверки пути NextPDF\Enterprise\Security\Pki и BatchSignatureValidator. Руководство на уровне рабочих процессов см. в Проверка подписи: криптографическая сторона проверки AdES / PAdES.
Доступность и лицензирование
Заголовок раздела «Доступность и лицензирование»Эта возможность поставляется в составе NextPDF Enterprise (nextpdf/enterprise) и активируется лицензионным пакетом уровня Enterprise. Развёртывание без этого права не загружает классы данной возможности. Сравните редакции и получите лицензию.
Публичная поверхность API
Заголовок раздела «Публичная поверхность API»| Символ | Параметры | Поведение по умолчанию | Возвращает | Выбрасывает или завершается с | Примечания |
|---|---|---|---|---|---|
AdESValidationEngine::__construct | 11 необязательных параметров: ?PathValidatorInterface $chainValidator, ?SignatureDataExtractor $extractor, ClockInterface $clock, ?LoggerInterface $logger, string $defaultPolicy, NetworkPolicy $networkPolicy и пять необязательных верификаторов-коллабораторов | Все значения по умолчанию fail-closed: валидатор пути Pki поверх часов движка, без извлекателя, без хранилища доверия TSA | Новый движок | Не выбрасывает | Без хранилища доверия оценка цепочки TSA сообщает о недоверии; это отображается в INDETERMINATE, никогда в прохождение |
AdESValidationEngine::validateBasic | string $signedData, string $signature | Базовая проверка: формат, дайджест, крипто, слабый алгоритм, цепочка, отзыв с учётом происхождения | ValidationReport | Не выбрасывает; ошибки извлечения и пути отображаются в отчёты fail-closed | Без извлекателя — только защитные проверки; см. крайние случаи |
AdESValidationEngine::validateWithTime | string $signedData, string $signature, DateTimeImmutable $claimedTime | Сначала базовая проверка; окно сертификата и отзыв сравниваются с заявленным временем | ValidationReport | Не выбрасывает | Строгий контроль метки времени подписи при наличии атрибута; $claimedTime остаётся временным якорем |
AdESValidationEngine::validateWithLongTermData | string $signedData, string $signature, array $dssData (certs/ocsps/crls) | Требуется прохождение базовой проверки; контроль метки времени подписи с проверкой TSA на genTime; контроли POE, отзыва DSS и архивные | ValidationReport | Не выбрасывает | NetworkPolicy::STRICT_OFFLINE при недостатке встроенных данных даёт INDETERMINATE / TRY_LATER |
AdESValidationEngine::validateArchivalTimestampChain | string $pdfBytes, array $dssData = [], ?TrustAnchorStoreInterface $anchors = null | Основанная на доказательствах цепочка покрытия DocTimeStamp по точным байтам ByteRange | ValidationReport | Не выбрасывает на враждебных байтах | TOTAL_PASSED только для доверенной цепочки, покрывающей до EOF |
MainIndication | — | Перечисление на строках, три варианта | — | — | Значения URN ETSI; см. список вариантов ниже |
SubIndication | — | Перечисление на строках, пятнадцать вариантов | — | — | Значения URN ETSI; см. список вариантов ниже |
ValidationReport::__construct | MainIndication $mainIndication, ?SubIndication $subIndication, DiagnosticData $diagnosticData, DateTimeImmutable $validationTime, string $validationPolicy = '' | Неизменяемый (final readonly) результат проверки | Новый отчёт | Не выбрасывает | isPassed(), isFailed(), isIndeterminate(), toArray() |
DiagnosticData::__construct | array $certificateChain, array $timestamps, array $revocationData, string $validationPolicy, string $signatureFormat, array $warnings (все со значениями по умолчанию) | Неизменяемый контейнер доказательств; только для журнала аудита | Новое значение | Не выбрасывает | toArray() сериализует ссылки для отчётности |
SignatureDataExtractor::extract | string $signedData, string $signature | SPI: разобрать CMS и извлечь компоненты проверки | ExtractedSignatureData | SignatureExtractionException, когда подпись не удаётся разобрать | Интерфейс; отделяет разбор ASN.1 от движка |
CmsSignatureDataExtractor::extract | string $signedData, string $signature | Извлечение плюс криптографическая проверка отделённой базовой подписи PAdES | ExtractedSignatureData | SignatureExtractionException только когда CMS вообще не удаётся разобрать | Ошибка крипто или привязки возвращает данные с cryptoValid / hashValid равными false; для этого исключение никогда не выбрасывается |
PdfSignatureDictionaryScanner::scan | string $pdfBytes | Побайтовое сканирование словарей /ByteRange + /Contents с точными перекрёстными антиподменными проверками | list<PdfSignatureOccurrence> | Тотальная; никогда не выбрасывает; некорректные кандидаты пропускаются | Упорядочено по концу покрытия, сначала самые ранние |
PathValidatorInterface::validate | array $chain, ?DateTimeImmutable $validationTime = null, array $initialPolicies = [] | Проверка пути по RFC 5280 §6.1.4 с обработкой политик | PathValidationResult | PathValidationException при структурно недопустимой цепочке или превышении враждебного лимита | Цепочка: сначала конечный субъект, якорь последним |
PathValidatorInterface::validateWithAiaChasing | array $chain, ?DateTimeImmutable $validationTime = null | Разрешение через AIA недостающих промежуточных сертификатов, затем проверка | PathValidationResult | PathValidationException | Загрузки ограничены таймаутом и лимитами байтов |
CertificateChainValidator | Конструктор: движок, PathValidationOptions, часы, логгер; статический withDefaults() | Реализация SPI с враждебными лимитами по умолчанию | PathValidationResult из обоих методов | PathValidationException | Также выбрасывается, когда OpenSSLCertificate не удаётся экспортировать в PEM |
PathValidationOptions::__construct | Лимиты (maxDepth, maxPolicyFanout, fetchTimeoutSeconds, fetchSizeCapBytes) плюс флаги политик, ?TrustAnchorStoreInterface $trustAnchors, bool $requireTrustedAnchor | Глубина 32, разветвление 64, 5 с на загрузку, 10 MiB на загрузку; все флаги false | Новые параметры | Не выбрасывает | Фабрики: defaults(), strict(), withTrustAnchors() |
PathValidationResult::__construct | bool $valid, string $trustAnchorFingerprint, DateTimeImmutable $validatedAt, array $validPolicies, ?RevocationCheckResult $revocation, bool $trustAnchorTrusted, array $fetchedCertificates, array $failureReasons | Неизменяемый результат; trustAnchorTrusted по умолчанию false (fail-closed) | Новое значение | Не выбрасывает | Членство в доверии отличается от структурной валидности |
PolicyProcessor | Конструктор: PolicyTreeState $state, PathValidationOptions $options; processCertificate(string $certDer, int $depth, bool $selfIssued), finalizeWrapUp(), tree() | Расширение, отображение и завершение дерева политик по RFC 5280 §6.1.4 | void / list<non-empty-string> / PolicyTree | PathValidationException при любой ошибке обработки политик (fail-closed) | Завершение возвращает уцелевшие OID политик, исключая anyPolicy |
PolicyTree | attach(PolicyTreeNode $node, PathValidationOptions $options), enforceFanout(...), remove(...), плюс запросы на чтение | Состояние valid_policy_tree с индексом глубины | Зависит от метода | PathValidationException, когда число живых листьев превышает лимит разветвления | Предоставляет ANY_POLICY_OID (2.5.29.32.0) |
NameConstraintsChecker::processCertificate | string $certDer, bool $applyNameCheck | Накапливает и применяет разрешённые / исключённые поддеревья согласно RFC 5280 §6.1.4(g) | void | PathValidationException при нарушении поддерева, неподдерживаемой форме GeneralName в ограничении или превышении лимита | Несравнимые имена обрабатываются по принципу fail-closed |
TrustAnchorStoreInterface::containsFingerprint | string $anchorDerSha256Hex | Членство по SHA-256 в нижнем регистре hex над DER-сертификатом якоря | bool | Не выбрасывает | Шов доверия, к которому обращается валидатор пути |
BatchSignatureValidator::validate | array $inputs (list<DocumentSignatureInput>) | Проверка подписей нескольких документов с кэшированием отзыва в пределах пакета | BatchValidationReport | InvalidArgumentException при пустом списке; ресурсный ограничитель отклоняет пакеты свыше 1000 документов | Находится в NextPDF\Enterprise\Signature |
final class AdESValidationEnginepublic function validateBasic(string $signedData, string $signature): ValidationReportpublic function validateWithTime( string $signedData, string $signature, DateTimeImmutable $claimedTime,): ValidationReportpublic function validateWithLongTermData( string $signedData, string $signature, array $dssData,): ValidationReportpublic function validateArchivalTimestampChain( string $pdfBytes, array $dssData = [], ?TrustAnchorStoreInterface $anchors = null,): ValidationReportpublic function validate( array $chain, ?DateTimeImmutable $validationTime = null, array $initialPolicies = [],): PathValidationResult;public function validateWithAiaChasing( array $chain, ?DateTimeImmutable $validationTime = null,): PathValidationResult;public static function withDefaults( ?ClockInterface $clock = null, ?AiaChaser $aiaChaser = null, ?LoggerInterface $logger = null,): selfpublic function containsFingerprint(string $anchorDerSha256Hex): bool;public function extract(string $signedData, string $signature): ExtractedSignatureData;public function scan(string $pdfBytes): arraypublic function validate(array $inputs): BatchValidationReportПеречисления индикаций. Варианты MainIndication: TOTAL_PASSED, TOTAL_FAILED, INDETERMINATE. Базовые значения следуют шаблону urn:etsi:019102:mainindication:total-passed (нижний регистр, через дефис). Варианты SubIndication: HASH_FAILURE, SIG_CRYPTO_FAILURE, REVOKED, EXPIRED, NOT_YET_VALID, NO_POE, TRY_LATER, CERTIFICATE_CHAIN_GENERAL_FAILURE, FORMAT_FAILURE, REVOKED_CA_NO_POE, CRYPTO_CONSTRAINTS_FAILURE, POLICY_PROCESSING_FAILURE, REVOCATION_OUT_OF_BOUNDS_NO_POE, NO_SIGNING_CERTIFICATE_FOUND, TIMESTAMP_ORDER_FAILURE. Каждый подкреплён urn:etsi:019102:subindication:<CASE_NAME> с точным именем варианта.
Контракт поведения
Заголовок раздела «Контракт поведения»- Отчёты на входе, отчёты на выходе. Четыре точки входа движка возвращают
ValidationReportдля враждебного ввода вместо выбрасывания исключения. ПерехваченноеSignatureExtractionExceptionнаправляется на защитный путь; перехваченноеPathValidationExceptionотображается вTOTAL_FAILED/CERTIFICATE_CHAIN_GENERAL_FAILURE. - Порядок базовой проверки. Сначала проверка формата; неразбираемая структура — это
TOTAL_FAILED/FORMAT_FAILURE(EN 319 102-1 §5.3.4). Затем дайджест (HASH_FAILURE) и криптографическая проверка (SIG_CRYPTO_FAILURE), что соответствует результатам строительного блока EN 319 102-1 §5.2.7.4. Дайджест пересчитывается верификатором и сравнивается с подписанным атрибутомmessageDigest(RFC 5652 §5.6); дайджесты, предоставленные производителем, никогда не считаются доверенными. - Слабые алгоритмы понижают результат. Подпись, проходящая проверку под SHA-1 или со слабой привязкой сертификата подписи, возвращает
INDETERMINATE/CRYPTO_CONSTRAINTS_FAILURE, никогдаTOTAL_PASSED. Временной путь подтверждает это повторно, так что слабая подпись никогда не отмывается в проходной результат, действительный по времени. - Контроль происхождения отзыва. Флаги отзыва извлекателя учитываются только тогда, когда извлекатель действительно выполнил проверку отзыва (
revocationCheckedравно true). Непроверенное значение по умолчанию — это ни “подтверждено, что не отозвано”, ни триггерREVOKED. Доказательство отзыва устанавливается путём DSS. - Распространение непрохождения. Временной и долгосрочный пути никогда не повышают непроходной базовый результат. Существует одно исключение: базовый
INDETERMINATE/REVOKEDразрешается относительно$claimedTime; отзыв в момент заявленного времени или ранее — этоTOTAL_FAILED/REVOKED. Это отражает шаблон EN 319 102-1 §5.3.4 по разрешению связанной с отзывом неопределённости с помощью временного доказательства. Когда сравнение выполнить невозможно, неразрешённый базовый отчёт распространяется дословно. - Строгая привязка метки времени подписи (fail-closed; нарушение обратной совместимости). Когда CMS несёт неподписанный атрибут
id-aa-timeStampToken, его наличие запускает принудительную проверку и на временном, и на долгосрочном пути; режима “только предупреждение” нет. Кардинальность должна быть ровно один атрибут ровно с одним значением (EN 319 122-1 §5.3); любая иная форма — этоTOTAL_FAILED/FORMAT_FAILURE. Токен должен пройти криптографическую проверку от начала до конца; непроверяемый токен, конфликт различий парсеров или несовпадение отпечатка — этоINDETERMINATE/TIMESTAMP_ORDER_FAILURE. Неподдерживаемый или SHA-1 алгоритм отпечатка — этоINDETERMINATE/CRYPTO_CONSTRAINTS_FAILURE. Правило привязки — RFC 3161 Appendix A:messageImprintтокена должен быть равен хешу октетов значенияsignatureиз SignerInfo, сравниваемому за постоянное время. - Контроли долгосрочного пути. На пути, аннотированном пунктом 5.4, привязанная метка времени подписи дополнительно проходит оценку сертификата TSA на момент
genTimeтокена; недоверенный якорь — этоINDETERMINATE/CERTIFICATE_CHAIN_GENERAL_FAILURE, никогда прохождение.NetworkPolicy::STRICT_OFFLINEпри недостаточном встроенном материале DSS возвращаетINDETERMINATE/TRY_LATER. Доказательство существования, отзыв DSS и находки по архивной цепочке каждый раз замыкают наINDETERMINATEс сопоставленной субиндикацией. - Контроли архивной цепочки. Отсутствие DocTimeStamp — это
INDETERMINATE/NO_POE. Структурно несоответствующий ByteRange — этоTOTAL_FAILED/FORMAT_FAILURE. Каждый токен должен пройти проверку, привязать свой отпечаток к точным байтам, покрытым ByteRange, и пройти сопоставление аспектов TSA на genTime (EXPIRED,NOT_YET_VALID,REVOKED_CA_NO_POE,CERTIFICATE_CHAIN_GENERAL_FAILUREилиTRY_LATERв строгом офлайн-режиме). Порядок применяется принудительно: неубывающийgenTime, строго прогрессирующее покрытие и то, что более поздние токены содержат дырку/Contentsпредыдущего токена. Самый поздний токен должен покрывать финальный байт; замыкающие байты — этоTIMESTAMP_ORDER_FAILURE.genTime, опережающий часы верификатора более чем на 300 секунд, — этоTIMESTAMP_ORDER_FAILURE. - Диагностика никогда не решает. Записи доказательства существования в
DiagnosticData::$timestampsпредназначены только для журнала аудита. Они никогда не меняют индикацию, и накопитель сбрасывается на каждой точке входа. - Лимиты Pki предшествуют крипто. Лимиты
PathValidationOptions(глубина 32, разветвление политик 64, 5 с и 10 MiB на загрузку) проверяются до затратной работы.PathValidationResult::$trustAnchorTrustedотличается от$valid;requireTrustedAnchorделает неподтверждённую конечную точку недействительной.strict()включаетrequireExplicitPolicy, жёсткий отказ при транспорте отзыва иrequireTrustedAnchor. Действительность пути определяется относительно якоря согласно RFC 5280 §6.1: действительный путь начинается с якоря доверия, предоставленного на входе. - Пакетная поверхность.
BatchSignatureValidator::validate()выбрасываетInvalidArgumentExceptionдля пустого списка и отклоняет пакеты свыше 1000 документов через ресурсный ограничитель. PHP владеет всей криптографической проверкой в этом конвейере.
Крайние случаи и режимы отказа
Заголовок раздела «Крайние случаи и режимы отказа»- Движок по умолчанию не имеет извлекателя.
new AdESValidationEngine()выполняет только защитные проверки: пустая подпись или подписанные данные — этоTOTAL_FAILED; любая непустая пара разрешается вINDETERMINATE/NO_SIGNING_CERTIFICATE_FOUND, никогдаTOTAL_PASSED. ВнедритеNextPDF\Enterprise\Security\Validation\CmsSignatureDataExtractor, чтобы получить криптографическую проверку. - Проверка доверия TSA по умолчанию не имеет хранилища. Тогда каждая цепочка TSA сообщает о недоверии, поэтому архивные и долгосрочные результаты метки времени подписи остаются
INDETERMINATE. Предоставьте якоря черезvalidateArchivalTimestampChain(..., $anchors)или настроенныйTsaCertificateAtGenTimeCheck. - Пустые
$pdfBytes.validateArchivalTimestampChain('')возвращаетTOTAL_FAILED/FORMAT_FAILURE. - Метки времени подписи до исправления не могут пройти. Токены, созданные версиями NextPDF до исправления строгой привязки, отпечатывали другой ввод. Они навсегда не проходят привязку Appendix A; повторно подпишите и заново проставьте метку времени, чтобы восстановить положительный результат. Это преднамеренное, задокументированное нарушение обратной совместимости.
- Дублирующиеся или перекрывающиеся DocTimeStamp. Дубликат в той же ревизии, равное или перекрывающееся покрытие либо более поздний токен, не содержащий дырку подписи предыдущего токена, не проходит контроль порядка.
- Сканер тотальный и побайтовый.
scan()молча пропускает некорректных или подменных кандидатов; ложный/ByteRangeвнутри потока содержимого отклоняется. Он не разрешает косвенные объекты и не обходит таблицу перекрёстных ссылок. - Покрытие, а не достижимость.
validateArchivalTimestampChain()доказывает криптографическое покрытие диапазона байтов до конца файла. Анализ достижимости на уровне объектов (например, перенаправленный корень документа внутри покрытой ревизии) объявлен вне области действия. - Прямое использование Pki выбрасывает исключение. Прямой вызов реализаций
PathValidatorInterfaceпорождаетPathValidationExceptionдля структурно недопустимых цепочек, превышенных лимитов, неподдерживаемых форм ограничений и неудавшегося экспорта в PEM дескриптораOpenSSLCertificate. Движок перехватывает этот класс; ваши собственные вызывающие стороны должны его обрабатывать.
Поведение в режиме FIPS
Заголовок раздела «Поведение в режиме FIPS»Сторона проверки принимает RSA PKCS#1 v1.5 с SHA-2 и ECDSA на P-256/P-384/P-521. Токены RSASSA-PSS, EdDSA и SHA-3 завершаются с отказом как неподдерживаемые; SHA-1 понижается до CRYPTO_CONSTRAINTS_FAILURE. В профиле криптополитики Enterprise FIPS 140-3 (задокументирован вместе с модулем безопасности) ограничение применяется к тому, какие алгоритмы принимаются; сам процесс проверки — пересчёт дайджеста, проверки подписи, привязка, проверка пути — не меняется. NextPDF не обладает сертификатом FIPS 140-3, и эта страница его не заявляет.
Соответствие
Заголовок раздела «Соответствие»| Утверждение | Стандарт | Пункт |
|---|---|---|
| Проверка базовой подписи — это переиспользуемый строительный блок для проверки меток времени и проверки со временем. | ETSI EN 319 102-1 | §5.3.1 |
Ошибка целостности отображается в HASH_FAILURE; неудавшаяся проверка подписи отображается в SIG_CRYPTO_FAILURE. | ETSI EN 319 102-1 | §5.2.7.4 |
| Проверка формата выполняется первой, и непрохождение останавливает процесс. | ETSI EN 319 102-1 | §5.3.4 |
| Связанную с отзывом неопределённость можно разрешить с помощью временного доказательства. | ETSI EN 319 102-1 | §5.3.4 |
| Действительный путь сертификации начинается с якоря доверия, предоставленного на входе. | RFC 5280 | §6.1 |
Верификатор пересчитывает дайджест содержимого; он должен быть равен подписанному атрибуту messageDigest. | RFC 5652 | §5.6 |
messageImprint метки времени подписи хеширует значение поля signature из SignerInfo. | RFC 3161 | Appendix A |
Атрибут signature-time-stamp несёт ровно один AttributeValue. | ETSI EN 319 122-1 | §5.3 |
Все пункты изложены в пересказе; NextPDF не воспроизводит нормативный текст. NextPDF не делает заявлений о соответствии или сертификации AdES / PAdES. Поддержка стандарта не является соответствием ему, а соответствие не является сертификацией — NextPDF не обладает сертификацией и не предоставляет её. Движок реализует цитируемые процедуры проверки как возможность; это не квалифицированная и не сертифицированная служба проверки, а отчёт TOTAL_PASSED — это криптографическое утверждение, а не юридическое определение. Значения перечислений переиспользуют шаблон идентификаторов URN ETSI для интероперабельности данных отчёта; такое переиспользование не подразумевает никакого одобрения.
Заметки для разработки
Заголовок раздела «Заметки для разработки»- Сопоставление меток пунктов. Исходный код пакета аннотирует точки входа как пункты EN 319 102-1 5.2, 5.3 и 5.4. Корпус соответствия помещает сам процесс проверки базовой подписи в пункт 5.3, а криптографический строительный блок — в 5.2.7.4. Эта страница цитирует извлечённые номера пунктов; авторитетен контракт поведения, а не метка.
- Детерминированные тесты. Каждое сравнение времени проходит через внедрённый PSR-20
ClockInterface. Внедрите замороженные часы, чтобы тестировать проверки окна, границу расхождения genTime в 300 секунд и решения о свежести CRL. - Композиция. Все коллабораторы движка внедряются через конструктор и являются необязательными, со значениями по умолчанию fail-closed. Валидатор пути по умолчанию —
CertificateChainValidator::withDefaults()поверх часов движка; параметры по умолчанию делают обработку политик и ограничений имён холостой операцией для соответствующих, неограниченных входных данных. - Пространства имён. Поверхность движка находится в
NextPDF\Enterprise\Security\Validation, поверхность проверки пути — вNextPDF\Enterprise\Security\Pki, а пакетный оркестратор — вNextPDF\Enterprise\Signature. - Гигиена отчётов. Отчёты неизменяемы и сериализуются через
toArray(). Диагностический контекст сбрасывается на каждой точке входа, поэтому отчёт никогда не несёт доказательств из предыдущего запуска на том же экземпляре движка.
См. также
Заголовок раздела «См. также»- Проверка подписи: криптографическая сторона проверки AdES / PAdES — страница возможности: рабочий процесс, таблица алгоритмов, заметки об обновлении.
- Подпись — подробный справочник — сторона производителя PAdES B-LT / B-LTA.
- Проверка — подробный справочник — структурные проверки политик без криптографии.
- Безопасность — подробный справочник — объединённая поверхность безопасности Enterprise, включая профиль FIPS.
- Карта пунктов PAdES — B-B, B-T, B-LT, B-LTA по редакциям.
Граница публикации
Заголовок раздела «Граница публикации»Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов руководств по эксплуатации и префиксы тикетов находятся вне области действия.