Enterprise редакция
Уровни доверия eIDAS
Краткий обзор
Заголовок раздела «Краткий обзор»NextPDF Enterprise превращает доказательства из доверенных списков ЕС в явный уровень доверия eIDAS (LoA). Служба NextPDF\Enterprise\Security\Eidas\LoaMapping классифицирует одну запись доверенной службы как Low, Substantial или High. Она возвращает LoaAssertion, несущий уровень плюс машиночитаемые коды причин. Ваш рабочий процесс может использовать доверие как условие — «требовать High» — и архивировать причины как аудиторское доказательство. Сопутствующий страж, CertPiiGuard, скрывает поля идентификации подписанта до того, как аудиторские записи покинут процесс.
Две границы честно очерчивают эту возможность. Во-первых, квалификация всегда принадлежит поставщику доверенных услуг (TSP) под надзором государства-члена. NextPDF утверждает классификацию поверх опубликованных доказательств; он никогда не предоставляет, не присваивает и не сертифицирует квалификацию. Во-вторых, эта страница охватывает только утверждение и сопоставление LoA. Структурная политика PAdES eidasQualified(), включая её критерии успеха/неудачи, описана в Валидации.
Доступность и лицензирование
Заголовок раздела «Доступность и лицензирование»Эта возможность поставляется в NextPDF Enterprise (nextpdf/enterprise) и активируется лицензионным конвертом уровня Enterprise. Развёртывание без этого права не загружает классы этой возможности. Сравните редакции и получите лицензию.
Установка
Заголовок раздела «Установка»composer require nextpdf/enterpriseМетапакет nextpdf/premium также подтягивает пакет Enterprise. Активация использует ваш лицензионный конверт Enterprise; см. Лицензирование и активация. Классам eIDAS не требуется никакого PHP-расширения сверх базового набора движка. Они автозагружаются в NextPDF\Enterprise\Security\Eidas и NextPDF\Enterprise\Signature\Eidas.
Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Regulation (EU) No 910/2014 (eIDAS) определяет три уровня доверия: низкий, существенный и высокий (Article 8(1)). Каждый уровень выражает степень уверенности в заявленной идентичности. Высокий уровень добавляет средства контроля, цель которых — предотвратить, а не просто уменьшить, злоупотребление идентичностью или её изменение (Article 8(2)(c)). Article 8 определяет эти уровни для схем электронной идентификации. NextPDF повторно использует ту же терминологию для классификации доказательств доверенной службы, стоящих за сертификатом подписания. Такое повторное использование — инженерное соглашение для управления политиками и аудита, а не юридическая эквивалентность.
Перечисление LoaLevel моделирует три уровня. Его подставляемые значения — это URI уровней доверия eIDAS, а не голые метки, поэтому сохранённое утверждение несёт полный идентификатор. rank() задаёт полный порядок (Low = 1, Substantial = 2, High = 3), а meetsOrExceeds() сравнивает с требуемым минимумом.
LoaMapping вычисляет уровень из одной записи доверенного списка — TspService из подсистемы доверенных списков Enterprise (NextPDF\Enterprise\Security\Tsl). Сопоставление детерминировано:
| Доказательство из доверенного списка | Уровень | Коды причин |
|---|---|---|
| Статус службы не granted | Low | service_not_granted |
Тип службы не CA/QC | Low | service_not_qualified_ca |
Granted CA/QC с QCWithQSCD и без QCNoQSCD | High | ca_qc_with_qscd плюс esig_or_eseal или qc_default |
Granted CA/QC в остальных случаях | Substantial | ca_qc_no_qscd_or_unspecified |
Квалификатор QSCD (квалифицированное устройство создания подписи) — это ключевой рычаг. Согласно Article 3(12), квалифицированная электронная подпись требует как квалифицированного сертификата, так и квалифицированного устройства создания. Поэтому заявление в доверенном списке о том, что сертификаты управляются на QSCD, является доказательством, поддерживающим утверждение High. Без такого заявления granted-квалифицированный CA всё ещё поддерживает Substantial, но никогда High.
Результат — это LoaAssertion: уровень плюс список кодов причин. Причины позволяют потребителю аудита позже повторно вывести классификацию из тех же доказательств. Нижестоящие вычислители политик могут записать это утверждение рядом с исходом валидации подписи.
Ещё один элемент поставляется в этом модуле: CertPiiGuard. Когда артефакты валидации сериализуются в JSON-пакеты аудита, сертификат подписанта несёт персональные данные — Subject CN, атрибуты email и атрибут serialNumber, который может кодировать национальный идентификатор для физических лиц. GDPR Article 5(1)(c) требует, чтобы обработка была ограничена необходимым. Поэтому страж по умолчанию скрывает эти поля, заменяя значения на [REDACTED] и сохраняя структурную оболочку (поля организации, страны, цепочки и статуса). Потребители всё ещё могут проверить, прошла ли подпись, не узнавая, кто подписал.
Почему это работает именно так
Заголовок раздела «Почему это работает именно так»Определяющее решение — отделение утверждения о доверии от вердикта валидации. Валидация подписи, согласно ETSI EN 319 102-1, заканчивается индикацией статуса — TOTAL-PASSED, TOTAL-FAILED или INDETERMINATE — и этот вердикт принадлежит слою валидации. Сопоставление LoA — это отдельная, воспроизводимая классификация поверх доказательств из доверенного списка, с кодами причин вместо голой метки. Это удерживает NextPDF от того, чтобы когда-либо представлять утверждение о доверии как результат валидации или результат валидации как предоставление квалификации. Это также делает сопоставление консервативным по построению: отсутствующие или неоднозначные доказательства понижают уровень, но никогда не повышают его.
Проектная предыстория: Квалифицированные подписи: объяснение.
Поверхность API
Заголовок раздела «Поверхность API»Все символы ниже — это публичный API в nextpdf/enterprise 3.1.0.
LoaLevel
Заголовок раздела «LoaLevel»enum LoaLevel: string{ case Low = 'http://eidas.europa.eu/LoA/low'; case Substantial = 'http://eidas.europa.eu/LoA/substantial'; case High = 'http://eidas.europa.eu/LoA/high';
public function rank(): int
public function meetsOrExceeds(self $required): bool}Выбрасывает или отказывает с: ничего от rank() или meetsOrExceeds(). Нативное создание перечисления через LoaLevel::from() выбрасывает \ValueError на нераспознанном URI; LoaLevel::tryFrom() вместо этого возвращает null.
LoaMapping
Заголовок раздела «LoaMapping»final class LoaMapping{ public function loaForService(TspService $service): LoaAssertion}Выбрасывает или отказывает с: ничего. Метод тотален — каждый вход TspService даёт LoaAssertion.
Входные DTO NextPDF\Enterprise\Security\Tsl\TspService и NextPDF\Enterprise\Security\Tsl\TspServiceQualifier — стабильные публичные DTO (@api). Сопоставление обращается к TspService::STATUS_GRANTED, TspService::TYPE_CA_QC и константам квалификаторов TspServiceQualifier::QSCD_STATEMENT (QCWithQSCD), TspServiceQualifier::NO_QSCD (QCNoQSCD), TspServiceQualifier::FOR_ESIG и TspServiceQualifier::FOR_ESEAL.
LoaAssertion
Заголовок раздела «LoaAssertion»final readonly class LoaAssertion{ /** * @param list<non-empty-string> $reasons Machine-readable reason codes for the assertion. */ public function __construct( public LoaLevel $level, public array $reasons, ) {}}Выбрасывает или отказывает с: ничего. Неизменяемый объект-значение.
CertPiiGuard
Заголовок раздела «CertPiiGuard»final readonly class CertPiiGuard{ public function __construct( private bool $disclosePii = false, ) {}
public function disclosesPii(): bool
public function guardSignerCommonName(string $signer): string
public function guardDistinguishedName(string $dn): string
public function guardTsaName(string $tsaName): string
public function guardRootIssuer(string $issuer): string
public function guardChainIssue(string $issue): string}Выбрасывает или отказывает с: ничего. Стражи — это чистые строковые преобразования. На компоненте DN, который не удаётся уверенно токенизировать, страж отказывает безопасно и сворачивает компонент в [REDACTED] вместо выдачи частично замаскированного значения.
Пример кода — Быстрый старт
Заголовок раздела «Пример кода — Быстрый старт»Разберите URI LoA и сравните его с требуемым минимумом.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Eidas\LoaLevel;
// A LoA URI as persisted in an audit record or received from a peer system.$uri = 'http://eidas.europa.eu/LoA/substantial';
try { $level = LoaLevel::from($uri);} catch (\ValueError $e) { // Unknown URI: refuse to classify. Never guess an assurance level. echo "Unrecognized LoA URI: {$uri}\n"; exit(1);}
echo 'Level: ' . $level->name . ' (rank ' . $level->rank() . ")\n";echo 'Meets substantial: ' . ($level->meetsOrExceeds(LoaLevel::Substantial) ? 'yes' : 'no') . "\n";echo 'Meets high: ' . ($level->meetsOrExceeds(LoaLevel::High) ? 'yes' : 'no') . "\n";Ожидаемый вывод:
Level: Substantial (rank 2)Meets substantial: yesMeets high: noПример кода — Продакшн
Заголовок раздела «Пример кода — Продакшн»Классифицируйте запись доверенного списка, примените условие требуемого уровня и выдайте отредактированную аудиторскую запись.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Enterprise\Security\Eidas\LoaLevel;use NextPDF\Enterprise\Security\Eidas\LoaMapping;use NextPDF\Enterprise\Security\Tsl\TspService;use NextPDF\Enterprise\Security\Tsl\TspServiceQualifier;use NextPDF\Enterprise\Signature\Eidas\CertPiiGuard;
// Normally produced by the Enterprise trusted-list subsystem from a// member-state TSL; constructed inline here for a self-contained example.$caPem = (string) file_get_contents(__DIR__ . '/example-qc-ca.pem');
$service = new TspService( tspName: 'Example Qualified TSP', serviceName: 'Example Qualified CA G2', serviceTypeIdentifier: TspService::TYPE_CA_QC, serviceStatus: TspService::STATUS_GRANTED, statusStartingTime: '2024-01-01T00:00:00Z', serviceCertificatePem: $caPem, qualifiers: [ new TspServiceQualifier(qualifierUri: TspServiceQualifier::QSCD_STATEMENT), new TspServiceQualifier(qualifierUri: TspServiceQualifier::FOR_ESIG), ], additionalServiceInformation: [],);
try { // Required floor from deployment configuration; defaults to High. $required = LoaLevel::from(getenv('LOA_REQUIRED') ?: LoaLevel::High->value);} catch (\ValueError $e) { echo "Invalid LOA_REQUIRED URI; refusing to continue.\n"; exit(1);}
$mapping = new LoaMapping();$assertion = $mapping->loaForService($service);
// Privacy by default: signer identity fields are redacted in audit output.$guard = new CertPiiGuard();
$audit = [ 'loa' => $assertion->level->value, 'reasons' => $assertion->reasons, 'meets_required' => $assertion->level->meetsOrExceeds($required), 'signer' => $guard->guardSignerCommonName('CN=Jane Example, O=Example Corp, C=DE'),];
echo json_encode($audit, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";Ожидаемый вывод:
{ "loa": "http://eidas.europa.eu/LoA/high", "reasons": [ "ca_qc_with_qscd", "esig_or_eseal" ], "meets_required": true, "signer": "CN=[REDACTED], O=Example Corp, C=DE"}Крайние случаи и подводные камни
Заголовок раздела «Крайние случаи и подводные камни»LoaLevel::from()выбрасывает\ValueErrorна неизвестных URI. ИспользуйтеLoaLevel::tryFrom()там, где предпочтительна обработкаnull.- Противоречивые доказательства об устройстве остаются консервативными. Служба, несущая одновременно
QCWithQSCDиQCNoQSCD, сопоставляется сSubstantial, а неHigh. - Granted-служба
CA/QCбез квалификаторов сопоставляется сSubstantialи причинойca_qc_no_qscd_or_unspecified— квалифицирована по умолчанию, устройство не доказано. - URI квалификаторов вне отслеживаемого набора не влияют на классификацию. Неизвестные или будущие квалификаторы никогда не повышают уровень.
- Сопоставление читает только текущий статус службы. Оно не оценивает историю
statusStartingTime; окна на момент времени принадлежат слою валидации. - Сохраняйте подставляемый URI перечисления, а не целое число
rank(). Ранги существуют только для сравнения. CertPiiGuardсворачивает голое имя без=целиком в[REDACTED]; пустые строки проходят через все стражи без изменений.- Устаревшие DN OpenSSL с разделителем-слэшем обнаруживаются и маскируются структурно.
/внутри значения RFC 4514 трактуется как содержимое, а не разделитель. - Не-PII атрибуты DN (
O,OU,C,ST,L) сохраняются, поэтому рассуждения о юрисдикции переживают редактирование.
Заметки по безопасности
Заголовок раздела «Заметки по безопасности»- Конфиденциальность по умолчанию. Конструктор стража по умолчанию использует
disclosePii: false. Создавайтеnew CertPiiGuard(disclosePii: true)только там, где у вас есть документированное законное основание для обработки идентичности подписанта. Это реализует минимизацию данных GDPR Article 5(1)(c) на границе сериализации. - Безопасное редактирование. Когда компонент DN не удаётся уверенно токенизировать, весь компонент сворачивается в
[REDACTED]. Средство защиты конфиденциальности никогда не отказывает небезопасно. - Детерминированный вывод. Стражи используют чистую обработку строк — без часов, без случайности — поэтому замаскированный вывод байтово стабилен для идентичного входа. Стабильный вывод сохраняет осмысленность аудиторских диффов.
- Редактирование — это не шифрование.
[REDACTED]удаляет значение из записи. Если вам нужна восстанавливаемость идентичности, храните её отдельно под собственным законным основанием и контролем доступа. - Мусор на входе — мусор на выходе.
LoaAssertionнадёжен ровно настолько, насколько надёжны доказательства из доверенного списка за ним. Получайте и проверяйте подпись доверенных списков через подсистему доверенных списков Enterprise, прежде чем подавать записи в сопоставление.
Соответствие
Заголовок раздела «Соответствие»NextPDF Enterprise реализует поведение, основанное на Regulation (EU) No 910/2014 Article 8 (уровни доверия) и Article 3(12) (элементы квалифицированной электронной подписи), а также на терминологии квалификаторов доверенных списков ETSI. Поддержка — это не соответствие, а соответствие — это не сертификация. NextPDF не обладает сертификацией и не предоставляет её. NextPDF не является квалифицированным поставщиком доверенных услуг, органом оценки соответствия или надзорным органом. LoaAssertion — это программная классификация опубликованных доказательств. Это не юридическое определение квалификации или доверия, и оно не может сделать подпись квалифицированной.
Regulation (EU) 2024/1183 (eIDAS 2) продолжает ссылаться на уровни Article 8 и требует, чтобы Европейские кошельки цифровой идентичности предоставлялись на высоком уровне доверия. Эта страница цитирует это как регуляторный контекст; NextPDF не делает никаких заявлений о возможностях, связанных с кошельками.
Удовлетворяет ли конкретная подпись структурной политике, ориентированной на eIDAS, — это отдельный вопрос, на который отвечает модуль валидации; см. Валидацию.
Поведение в режиме FIPS
Заголовок раздела «Поведение в режиме FIPS»Классы LoA eIDAS не выполняют никаких криптографических операций — ни хеширования, ни проверки подписи, ни генерации случайности. Политика режима FIPS в Enterprise регулирует криптографический выбор, поэтому в этом модуле ей нечего регулировать. Включение режима FIPS не изменяет сопоставление LoA или поведение стража PII. Криптографическая проверка подписей и доверенных списков управляется модулями верификации и безопасности, где применяется политика режима FIPS.
Контракт поведения
Заголовок раздела «Контракт поведения»LoaMapping::loaForService()тотален и детерминирован. КаждыйTspServiceдаётLoaAssertion; метод никогда не выбрасывает и не обращается к часам, сети или глобальному состоянию.- Классификация консервативна. Отсутствующие, неизвестные или противоречивые доказательства понижают уровень; ничто не повышает его, кроме явных доказательств granted-
CA/QC-с-QSCD. - Коды причин машиночитаемы и стабильны:
service_not_granted,service_not_qualified_ca,ca_qc_with_qscd,esig_or_eseal,qc_default,ca_qc_no_qscd_or_unspecified. - Порядок уровней фиксирован:
Low<Substantial<High, доступен черезrank()иmeetsOrExceeds(). CertPiiGuardпо умолчанию редактирует и отказывает безопасно при сомнении в токенизации. ПриdisclosePii: trueкаждый страж возвращает свой вход дословно.- Вывод стража байтово стабилен для идентичного входа.
Запасной вариант в Core
Заголовок раздела «Запасной вариант в Core»NextPDF Core проверяет подписи PDF криптографически и отказывает безопасно на повреждённых доказательствах. У Core нет модели доверенных списков ЕС, нет терминологии LoaLevel, нет сопоставления LoA и нет стража PII слоя eIDAS для сериализации аудита. На одном лишь Core вы должны сами выводить классификации доверия из данных доверия, которые вы поддерживаете, и применять собственное редактирование до того, как аудиторские записи покинут процесс.
Граница публикации
Заголовок раздела «Граница публикации»Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов ранбуков и префиксы тикетов выходят за рамки.
См. также
Заголовок раздела «См. также»- Валидация — структурные политики соответствия, включая семантику
eidasQualified()и критерии успеха/неудачи - Проверка подписи — криптографическая сторона проверки AdES/PAdES, чьи отчёты защищает страж PII
- Безопасность — Глубокий справочник — глубокий справочник модуля безопасности
- Квалифицированные подписи: объяснение — Insider-эссе о квалификации и доверии
- Как подпись доказывает, кто подписал — Insider-эссе о доверии на стороне проверки