Enterprise edición
Niveles de seguridad eIDAS
En resumen
Sección titulada «En resumen»NextPDF Enterprise convierte la evidencia de las listas de confianza de la UE en un nivel de seguridad (LoA) eIDAS explícito. El servicio NextPDF\Enterprise\Security\Eidas\LoaMapping clasifica una entrada de servicio de confianza como Low, Substantial o High. Devuelve una LoaAssertion que lleva el nivel más los códigos de motivo legibles por máquina. El flujo de trabajo puede aplicar un control basado en la seguridad —«exigir High»— y archivar los motivos como evidencia de auditoría. Un guardián complementario, CertPiiGuard, redacta los campos de identidad del firmante antes de que los registros de auditoría salgan del proceso.
Dos límites enmarcan esta capacidad con honestidad. Primero, la cualificación siempre corresponde al prestador de servicios de confianza (TSP) bajo la supervisión del Estado miembro. NextPDF asevera una clasificación sobre la evidencia publicada; nunca concede, confiere ni certifica la cualificación. Segundo, esta página cubre únicamente la aserción y el mapeo de LoA. La política estructural PAdES eidasQualified(), incluidos sus criterios de aprobación/rechazo, se documenta en Validación.
Disponibilidad y licencias
Sección titulada «Disponibilidad y licencias»Esta capacidad se distribuye en NextPDF Enterprise (nextpdf/enterprise) y se activa con un envoltorio de licencia de nivel Enterprise. Una implementación sin esa titularidad no carga las clases de la capacidad. Compare ediciones y obtenga una licencia.
Instalación
Sección titulada «Instalación»composer require nextpdf/enterpriseEl metapaquete nextpdf/premium también resuelve el paquete Enterprise. La activación utiliza el envoltorio de licencia Enterprise; consulte Licencias y activación. Las clases eIDAS no necesitan ninguna extensión de PHP más allá de la base del motor. Se autocargan bajo NextPDF\Enterprise\Security\Eidas y NextPDF\Enterprise\Signature\Eidas.
Panorama conceptual
Sección titulada «Panorama conceptual»El Reglamento (UE) n.º 910/2014 (eIDAS) define tres niveles de seguridad: low, substantial y high (artículo 8(1)). Cada nivel expresa un grado de confianza en una identidad reclamada. El nivel high añade controles cuyo propósito es prevenir —no solo reducir— el uso indebido o la alteración de la identidad (artículo 8(2)(c)). El artículo 8 define estos niveles para los esquemas de identificación electrónica. NextPDF reutiliza el mismo vocabulario para clasificar la evidencia de servicio de confianza que respalda un certificado de firma. Esa reutilización es una convención de ingeniería para el control de políticas y la auditoría, no una equivalencia jurídica.
La enumeración LoaLevel modela los tres niveles. Sus valores de respaldo son las URI de LoA de eIDAS en lugar de etiquetas simples, de modo que una aserción persistida lleve el identificador completo. rank() proporciona un orden total (Low = 1, Substantial = 2, High = 3), y meetsOrExceeds() compara con un umbral mínimo exigido.
LoaMapping calcula un nivel a partir de una entrada de lista de confianza —un TspService del subsistema de listas de confianza de Enterprise (NextPDF\Enterprise\Security\Tsl)—. El mapeo es determinista:
| Evidencia de lista de confianza | Nivel | Códigos de motivo |
|---|---|---|
| El estado del servicio no es granted | Low | service_not_granted |
El tipo de servicio no es CA/QC | Low | service_not_qualified_ca |
CA/QC con estado granted, con QCWithQSCD y sin QCNoQSCD | High | ca_qc_with_qscd más esig_or_eseal o qc_default |
CA/QC con estado granted en otro caso | Substantial | ca_qc_no_qscd_or_unspecified |
El cualificador QSCD (dispositivo cualificado de creación de firmas) es el eje. En virtud del artículo 3(12), una firma electrónica cualificada requiere tanto un certificado cualificado como un dispositivo cualificado de creación. Por tanto, una declaración en la lista de confianza de que los certificados se gestionan en un QSCD es la evidencia que respalda una aserción High. Sin esa declaración, una CA cualificada con estado granted sigue respaldando Substantial, nunca High.
El resultado es una LoaAssertion: el nivel más una lista de códigos de motivo. Los motivos permiten a un consumidor de auditoría volver a derivar la clasificación a partir de la misma evidencia más adelante. Los evaluadores de políticas posteriores pueden registrar la aserción junto con un resultado de validación de firma.
Este módulo incorpora una pieza más: CertPiiGuard. Cuando los artefactos de validación se serializan en paquetes de auditoría JSON, el certificado del firmante lleva datos personales: el CN del sujeto, los atributos de correo electrónico y el atributo serialNumber, que puede codificar un identificador nacional para personas físicas. El artículo 5(1)(c) del RGPD exige que el tratamiento se limite a lo necesario. Por ello, el guardián redacta esos campos de forma predeterminada, reemplazando los valores por [REDACTED] mientras conserva el envoltorio estructural (campos de organización, país, cadena y estado). Los consumidores aún pueden verificar si una firma se aprobó sin averiguar quién la firmó.
Por qué funciona así
Sección titulada «Por qué funciona así»La decisión fundamental es separar la aserción de seguridad del veredicto de validación. La validación de firma, según ETSI EN 319 102-1, termina en una indicación de estado —TOTAL-PASSED, TOTAL-FAILED o INDETERMINATE— y ese veredicto corresponde a la capa de validación. El mapeo de LoA es una clasificación distinta y reproducible sobre la evidencia de las listas de confianza, con códigos de motivo en lugar de una etiqueta simple. Esto evita que NextPDF presente jamás una afirmación de seguridad como un resultado de validación, o un resultado de validación como una concesión de cualificación. También hace que el mapeo sea conservador por construcción: la evidencia ausente o ambigua baja el nivel, nunca lo sube.
Contexto de diseño: Firmas cualificadas, explicadas.
Superficie de la API
Sección titulada «Superficie de la API»Todos los símbolos siguientes son API pública en nextpdf/enterprise 3.1.0.
LoaLevel
Sección titulada «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}Lanza o falla con: nada desde rank() ni meetsOrExceeds(). La construcción nativa de la enumeración mediante LoaLevel::from() lanza \ValueError ante una URI no reconocida; LoaLevel::tryFrom() devuelve null en su lugar.
LoaMapping
Sección titulada «LoaMapping»final class LoaMapping{ public function loaForService(TspService $service): LoaAssertion}Lanza o falla con: nada. El método es total: toda entrada TspService produce una LoaAssertion.
Los DTO de entrada NextPDF\Enterprise\Security\Tsl\TspService y NextPDF\Enterprise\Security\Tsl\TspServiceQualifier son DTO públicos estables (@api). El mapeo consulta TspService::STATUS_GRANTED, TspService::TYPE_CA_QC y las constantes de cualificador TspServiceQualifier::QSCD_STATEMENT (QCWithQSCD), TspServiceQualifier::NO_QSCD (QCNoQSCD), TspServiceQualifier::FOR_ESIG y TspServiceQualifier::FOR_ESEAL.
LoaAssertion
Sección titulada «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, ) {}}Lanza o falla con: nada. Objeto de valor inmutable.
CertPiiGuard
Sección titulada «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}Lanza o falla con: nada. Los guardianes son transformaciones puras de cadenas. Ante un componente de DN que no se puede tokenizar con confianza, el guardián falla de forma cerrada y colapsa el componente a [REDACTED] en lugar de emitir un valor parcialmente enmascarado.
Ejemplo de código — Inicio rápido
Sección titulada «Ejemplo de código — Inicio rápido»Analizar una URI de LoA y compararla con un umbral mínimo exigido.
<?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";Salida esperada:
Level: Substantial (rank 2)Meets substantial: yesMeets high: noEjemplo de código — Producción
Sección titulada «Ejemplo de código — Producción»Clasificar una entrada de lista de confianza, aplicar un control basado en un nivel exigido y emitir un registro de auditoría redactado.
<?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";Salida esperada:
{ "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"}Casos límite y trampas
Sección titulada «Casos límite y trampas»LoaLevel::from()lanza\ValueErrorante URI desconocidas. UtiliceLoaLevel::tryFrom()donde sea preferible el manejo denull.- La evidencia de dispositivo en conflicto se mantiene conservadora. Un servicio que lleva tanto
QCWithQSCDcomoQCNoQSCDse mapea aSubstantial, no aHigh. - Un servicio
CA/QCcon estado granted y sin cualificadores se mapea aSubstantialcon el motivoca_qc_no_qscd_or_unspecified: cualificado por defecto, dispositivo no probado. - Las URI de cualificador fuera del conjunto rastreado no afectan a la clasificación. Los cualificadores desconocidos o futuros nunca elevan el nivel.
- El mapeo lee únicamente el estado actual del servicio. No evalúa el historial de
statusStartingTime; las ventanas de punto en el tiempo corresponden a la capa de validación. - Persista la URI de respaldo de la enumeración, no el entero de
rank(). Los rangos existen solo para la comparación. CertPiiGuardcolapsa por completo a[REDACTED]un nombre simple sin=; las cadenas vacías pasan sin cambios por todos los guardianes.- Los DN heredados de OpenSSL separados por barras se detectan y se enmascaran estructuralmente. Una
/dentro de un valor RFC 4514 se trata como contenido, no como separador. - Los atributos de DN que no son PII (
O,OU,C,ST,L) se conservan, de modo que el razonamiento sobre la jurisdicción sobrevive a la redacción.
Notas de seguridad
Sección titulada «Notas de seguridad»- Privacidad por defecto. El constructor del guardián toma por defecto
disclosePii: false. Construyanew CertPiiGuard(disclosePii: true)solo donde disponga de una base jurídica documentada para tratar la identidad del firmante. Esto implementa la minimización de datos del artículo 5(1)(c) del RGPD en el límite de serialización. - Redacción de fallo cerrado. Cuando un componente de DN no se puede tokenizar con confianza, el componente completo colapsa a
[REDACTED]. Un control de privacidad nunca falla de forma abierta. - Salida determinista. Los guardianes usan procesamiento puro de cadenas —sin relojes, sin aleatoriedad—, de modo que la salida enmascarada es estable a nivel de bytes para una misma entrada. Una salida estable mantiene significativos los diffs de auditoría.
- La redacción no es cifrado.
[REDACTED]elimina el valor del registro. Si necesita que la identidad sea recuperable, almacénela por separado bajo su propia base jurídica y control de acceso. - Basura entra, basura sale. Una
LoaAssertionsolo es tan fiable como la evidencia de lista de confianza que la respalda. Adquiera y verifique la firma de las listas de confianza a través del subsistema de listas de confianza de Enterprise antes de alimentar las entradas al mapeo.
Conformidad
Sección titulada «Conformidad»NextPDF Enterprise implementa un comportamiento informado por el artículo 8 (niveles de seguridad) y el artículo 3(12) (elementos de una firma electrónica cualificada) del Reglamento (UE) n.º 910/2014, y por el vocabulario de cualificadores de listas de confianza de ETSI. El soporte no es conformidad, y la conformidad no es certificación. NextPDF no posee ninguna certificación ni concede ninguna. NextPDF no es un prestador cualificado de servicios de confianza, ni un organismo de evaluación de la conformidad, ni un organismo de supervisión. Una LoaAssertion es una clasificación de software de evidencia publicada. No es una determinación jurídica de cualificación ni de seguridad, y no puede hacer que una firma sea cualificada.
El Reglamento (UE) 2024/1183 (eIDAS 2) sigue haciendo referencia a los niveles del artículo 8 y exige que las carteras europeas de identidad digital se proporcionen con nivel de seguridad high. Esta página cita eso como contexto regulatorio; NextPDF no formula ninguna afirmación de capacidad relacionada con carteras.
Si una firma concreta satisface una política estructural orientada a eIDAS es una cuestión aparte, respondida por el módulo de validación; consulte Validación.
Comportamiento en modo FIPS
Sección titulada «Comportamiento en modo FIPS»Las clases de LoA eIDAS no realizan operaciones criptográficas: sin hashing, sin verificación de firma, sin aleatoriedad. La política de modo FIPS de Enterprise controla las decisiones criptográficas, de modo que no tiene nada que controlar en este módulo. Habilitar el modo FIPS no cambia el mapeo de LoA ni el comportamiento del guardián de PII. La verificación criptográfica de firmas y listas de confianza se rige por los módulos de verificación y seguridad, donde se aplica la política de modo FIPS.
Contrato de comportamiento
Sección titulada «Contrato de comportamiento»LoaMapping::loaForService()es total y determinista. Toda entradaTspServiceproduce unaLoaAssertion; el método nunca lanza y no consulta ningún reloj, red ni estado global.- La clasificación es conservadora. La evidencia ausente, desconocida o en conflicto baja el nivel; nada lo sube salvo evidencia explícita de
CA/QCcon estado granted y con QSCD. - Los códigos de motivo son legibles por máquina y estables:
service_not_granted,service_not_qualified_ca,ca_qc_with_qscd,esig_or_eseal,qc_default,ca_qc_no_qscd_or_unspecified. - El orden de los niveles es fijo:
Low<Substantial<High, expuesto medianterank()ymeetsOrExceeds(). CertPiiGuardtoma por defecto la redacción y falla de forma cerrada ante la duda de tokenización. CondisclosePii: true, cada guardián devuelve su entrada tal cual.- La salida del guardián es estable a nivel de bytes para una misma entrada.
Alternativa en Core
Sección titulada «Alternativa en Core»NextPDF Core verifica criptográficamente las firmas PDF y falla de forma cerrada ante evidencia rota. Core no tiene modelo de listas de confianza de la UE, ni vocabulario LoaLevel, ni mapeo de LoA, ni guardián de PII de capa eIDAS para la serialización de auditoría. Solo con Core, debe derivar usted mismo las clasificaciones de seguridad a partir de los datos de confianza que mantenga, y aplicar su propia redacción antes de que los registros de auditoría salgan del proceso.
Límite de publicación
Sección titulada «Límite de publicación»Esta página documenta únicamente el comportamiento observable externamente y la superficie de API pública admitida. Las rutas de espacio de nombres internas, las clases auxiliares, las tablas de mecanismos, los nombres de archivo de runbook y los prefijos de tickets quedan fuera de alcance.
Véase también
Sección titulada «Véase también»- Validación — políticas de conformidad estructural, incluida la semántica de
eidasQualified()y los criterios de aprobación/rechazo - Verificación de firmas — el lado de verificación criptográfica AdES/PAdES cuyos informes protege el guardián de PII
- Seguridad — Referencia detallada — la referencia detallada del módulo de Seguridad
- Firmas cualificadas, explicadas — ensayo Insider sobre cualificación y seguridad
- Cómo una firma prueba quién firmó — ensayo Insider sobre la confianza en el lado de verificación