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

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). Сопоставление детерминировано:

Доказательство из доверенного спискаУровеньКоды причин
Статус службы не grantedLowservice_not_granted
Тип службы не CA/QCLowservice_not_qualified_ca
Granted CA/QC с QCWithQSCD и без QCNoQSCDHighca_qc_with_qscd плюс esig_or_eseal или qc_default
Granted CA/QC в остальных случаяхSubstantialca_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 в nextpdf/enterprise 3.1.0.

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.

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.

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,
) {}
}

Выбрасывает или отказывает с: ничего. Неизменяемый объект-значение.

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 и сравните его с требуемым минимумом.

loa-quick-start.php
<?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: yes
Meets high: no

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

loa-audit-gate.php
<?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, — это отдельный вопрос, на который отвечает модуль валидации; см. Валидацию.

Классы 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 каждый страж возвращает свой вход дословно.
  • Вывод стража байтово стабилен для идентичного входа.

NextPDF Core проверяет подписи PDF криптографически и отказывает безопасно на повреждённых доказательствах. У Core нет модели доверенных списков ЕС, нет терминологии LoaLevel, нет сопоставления LoA и нет стража PII слоя eIDAS для сериализации аудита. На одном лишь Core вы должны сами выводить классификации доверия из данных доверия, которые вы поддерживаете, и применять собственное редактирование до того, как аудиторские записи покинут процесс.

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