Ir al contenido
getnextpdf.com

Enterprise edición

Niveles de seguridad eIDAS

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.

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.

Ventana de terminal
composer require nextpdf/enterprise

El 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.

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 confianzaNivelCódigos de motivo
El estado del servicio no es grantedLowservice_not_granted
El tipo de servicio no es CA/QCLowservice_not_qualified_ca
CA/QC con estado granted, con QCWithQSCD y sin QCNoQSCDHighca_qc_with_qscd más esig_or_eseal o qc_default
CA/QC con estado granted en otro casoSubstantialca_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ó.

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.

Todos los símbolos siguientes son API pública en 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
}

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.

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.

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.

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.

Analizar una URI de LoA y compararla con un umbral mínimo exigido.

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";

Salida esperada:

Level: Substantial (rank 2)
Meets substantial: yes
Meets high: no

Clasificar una entrada de lista de confianza, aplicar un control basado en un nivel exigido y emitir un registro de auditoría redactado.

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";

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"
}
  • LoaLevel::from() lanza \ValueError ante URI desconocidas. Utilice LoaLevel::tryFrom() donde sea preferible el manejo de null.
  • La evidencia de dispositivo en conflicto se mantiene conservadora. Un servicio que lleva tanto QCWithQSCD como QCNoQSCD se mapea a Substantial, no a High.
  • Un servicio CA/QC con estado granted y sin cualificadores se mapea a Substantial con el motivo ca_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.
  • CertPiiGuard colapsa 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.
  • Privacidad por defecto. El constructor del guardián toma por defecto disclosePii: false. Construya new 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 LoaAssertion solo 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.

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.

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.

  • LoaMapping::loaForService() es total y determinista. Toda entrada TspService produce una LoaAssertion; 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/QC con 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 mediante rank() y meetsOrExceeds().
  • CertPiiGuard toma por defecto la redacción y falla de forma cerrada ante la duda de tokenización. Con disclosePii: true, cada guardián devuelve su entrada tal cual.
  • La salida del guardián es estable a nivel de bytes para una misma entrada.

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.

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.