Inspeccionar una firma existente y comprender el límite de confianza
De un vistazo
Sección titulada «De un vistazo»Esta receta utiliza el inspector de Core para detectar si un PDF contiene una firma y, a continuación, delimitar el alcance. Detectar una firma no equivale a verificarla. La verificación criptográfica, la validación de la ruta de confianza y la comprobación de revocación pertenecen a Premium o a herramientas externas.
Requisitos previos
Sección titulada «Requisitos previos»- Core instalado:
composer require nextpdf/core:^3. - Un archivo PDF para inspeccionar.
- Leer los bytes del PDF.
- Crear un
Inspectory llamar ainspect(). - Leer
InspectResult::$hasSigned.truesignifica que existe un diccionario de firma en el archivo. - Leer
InspectResult::$isEncryptedy los indicadores de riesgo para conocer el contexto asociado. - Enviar el archivo a un verificador para la decisión criptográfica. El inspector informa sobre la presencia, no sobre la validez.
El diagrama siguiente muestra dos cosas: el límite que esta receta deja claro, la presencia no es validez, y el conjunto completo de comprobaciones que una verificación real todavía debe realizar.
Ejemplo completo
Sección titulada «Ejemplo completo»<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\Inspector;use NextPDF\Inspect\InspectConfig;
$pdfData = file_get_contents(__DIR__ . '/incoming.pdf');if ($pdfData === false || $pdfData === '') { fwrite(STDERR, "Cannot read incoming.pdf\n"); exit(1);}
$inspector = new Inspector();
// InspectConfig::quick() selects InspectDepth::Quick. This is the only// depth that runs offline: a default Inspector has no Spectrum sidecar,// and without a sidecar Quick is the sole path that returns a result.// Standard and Full require the sidecar (see the SIDECAR-001 edge case).$result = $inspector->inspect( $pdfData, InspectConfig::quick(),);
// hasSigned reports the PRESENCE of a signature dictionary.// It does NOT mean the signature verifies.if ($result->hasSigned) { echo "A signature is present in incoming.pdf\n"; echo "Encrypted: " . ($result->isEncrypted ? 'yes' : 'no') . "\n"; echo "Next step: run a cryptographic verifier before trusting it.\n";} else { echo "No signature found in incoming.pdf\n";}Salida esperada
Sección titulada «Salida esperada»Para una entrada firmada:
A signature is present in incoming.pdfEncrypted: noNext step: run a cryptographic verifier before trusting it.Para una entrada sin firmar:
No signature found in incoming.pdfCasos límite
Sección titulada «Casos límite»- La presencia no es validez: el límite.
InspectResult::$hasSignedindica que en el archivo existe un diccionario de firma. No comprueba la estructura CMS, el resumen del intervalo de bytes, el certificado de firma, la cadena de certificados ni el estado de revocación. Un archivo manipulado aún puede informar dehasSigned = true. Nunca se debe tratar la presencia como prueba de integridad ni de autoría. - Lo que necesita una verificación completa. Una decisión completa recalcula el resumen del intervalo de bytes y lo compara (ISO 32000-2 §12.8.1), valida CMS SignedData, construye y comprueba la ruta X.509 hasta un ancla de confianza y comprueba la revocación mediante OCSP o CRL. En entradas a largo plazo, los datos de validación residen en el DSS (ETSI EN 319 142-2 §6.3.1). Estas operaciones se realizan mediante los contratos
SignerInterfaceyLtvManagerInterface; las implementaciones de producción se incluyen en las ediciones Pro y Enterprise. Un validador externo es la otra ruta admitida. - Profundidad de la inspección y el sidecar (SIDECAR-001). Un
new Inspector()predeterminado no tiene configurado ningún sidecar de Spectrum. Sin un sidecar, soloInspectDepth::Quickdevuelve un resultado.InspectDepth::Quickusa el respaldo PHP en proceso.InspectDepth::StandardeInspectDepth::Fullrequieren ambas el sidecar. Sin un sidecar disponible, lanzanInspectExceptioncon el códigoINSPECT-SIDECAR-001(«Spectrum sidecar is required for Standard/Full depth inspection»,retryable = true). El constructor deInspectConfigtiene como profundidad predeterminadaStandard. Por lo tanto, unnew InspectConfig()sin parámetros (onew InspectConfig(depth: InspectDepth::Standard)) no puede usarse sin conexión. Lanza SIDECAR-001 antes incluso de quehasSignedllegue a leerse. UsarInspectConfig::quick()para la detección de presencia sin conexión, como se hace en esta receta. Ninguna de las profundidades realiza la verificación criptográfica de la firma en Core. - Entrada vacía. Una cadena vacía lanza
InspectExceptioncon el códigoINSPECT-INPUT-001. Proteger la lectura. - Varias firmas. El indicador de presencia no cuenta las firmas ni distingue una firma de aprobación de una marca de tiempo de documento. Usar un verificador específico cuando el recuento o el veredicto por firma sean relevantes.
Conformidad
Sección titulada «Conformidad»| Afirmación | Especificación | Cláusula | reference_id |
|---|---|---|---|
El valor de la firma se almacena en la entrada Contents del diccionario de firma. | ISO 32000-2 | §12.8.1 | |
La verificación recalcula el resumen sobre ByteRange, excluyendo el valor de la firma. | ISO 32000-2 | §12.8.1 | |
| Los datos de validación a largo plazo residen en el DSS. | ETSI EN 319 142-2 | §6.3.1 |
Esta receta detecta una firma. No afirma que una firma sea válida, de confianza o no revocada. Esa decisión corresponde a un verificador criptográfico.