Risoluzione dei problemi: firme e marche temporali
Queste schede riguardano gli errori di firma che il motore solleva tramite NextPDF\Exception\SignatureException e NextPDF\Security\Signature\Exception\SignatureLevelUnreachableException. Ogni scheda indica il metodo factory o la classe esatti, così da poter confermare la causa dal messaggio e da getContext() senza doverla dedurre.
Una nota sulla terminologia: il motore non certifica che una firma sia valida né che un documento sia protetto. Si limita a segnalare l’errore rilevato. Considerare ogni soluzione come un passaggio per rimuovere la causa segnalata.
Voce: il livello PAdES “B-LT” o “B-LTA” non può essere prodotto
Sezione intitolata “Voce: il livello PAdES “B-LT” o “B-LTA” non può essere prodotto”- Sintomo.
SignatureExceptioncon il messaggio terminante innextpdf/enterprise package is required for B-LT/B-LTA signatures. - Causa probabile. Manca il provider della capacità di convalida a lungo termine. B-LT e B-LTA incorporano il materiale di revoca e una marca temporale di archiviazione; questo provider è incluso in
nextpdf/enterprise. - Evidenza / diagnosi. Il factory
SignatureException::ltvCapabilityMissing()produce esattamente questo messaggio.getContext()restituiscesignature_levelimpostato sul livello richiesto. - Soluzione.
- Installare il provider: eseguire
composer require nextpdf/enterprise. - Rieseguire la chiamata di firma.
- Se non è possibile installare il provider, richiedere invece
B-BoB-T, prodotti dal pacchetto core.
- Installare il provider: eseguire
- Correlato. Riferimento delle eccezioni.
Voce: il livello di firma è irraggiungibile e la chiamata viene rifiutata
Sezione intitolata “Voce: il livello di firma è irraggiungibile e la chiamata viene rifiutata”- Sintomo.
SignatureLevelUnreachableExceptioncon un messaggio nella formaPAdES level "<x>" is unreachable (highest achievable: "<y>"). - Causa probabile. Il livello di conformità richiesto richiede un’infrastruttura non disponibile al momento della firma — il più delle volte un’autorità di marca temporale per B-T e superiori. Il motore adotta il fail-closed: non effettua silenziosamente un downgrade per poi dichiarare il livello superiore.
- Evidenza / diagnosi.
getContext()restituiscerequestedLevel,highestAchievableLevelereason. Il camporeasonindica la lacuna infrastrutturale. Questa è l’impostazione predefinita fail-closed, introdotta per impedire che un documento dichiari un livello che non soddisfa. - Soluzione.
- Leggere il campo
reasonper individuare l’infrastruttura mancante. - Fornire il componente mancante — ad esempio, configurare un’autorità di marca temporale — e rieseguire la chiamata.
- Per accettare intenzionalmente un livello inferiore, passare
allowDegradation: trueaPadesOrchestrator. La chiamata produce quindihighestAchievableLevele segnala il livello effettivamente prodotto.
- Leggere il campo
- Correlato. Cifratura e autorizzazioni.
Voce: il client dell’autorità di marca temporale è richiesto ma assente
Sezione intitolata “Voce: il client dell’autorità di marca temporale è richiesto ma assente”- Sintomo.
SignatureExceptioncon la terminazioneTSA client is required for level <x> but none was provided. - Causa probabile. Una richiesta B-T, B-LT o B-LTA richiede un client dell’autorità di marca temporale, ma nessun client è stato collegato all’orchestrator.
- Evidenza / diagnosi. Il factory
SignatureException::tsaRequired()produce questo messaggio;getContext()contiene ilsignature_levelrichiesto. - Soluzione.
- Configurare un client dell’autorità di marca temporale e passarlo all’orchestrator.
- Rieseguire la chiamata.
- Per produrre un livello che non necessita di marca temporale, richiedere
B-B.
- Correlato. Riferimento delle eccezioni.
Voce: l’URL dell’endpoint dell’autorità di marca temporale è vuoto
Sezione intitolata “Voce: l’URL dell’endpoint dell’autorità di marca temporale è vuoto”- Sintomo.
SignatureExceptioncon la terminazioneTSA endpoint URL is empty. - Causa probabile. Un client dell’autorità di marca temporale è stato costruito con un URL dell’endpoint vuoto.
- Evidenza / diagnosi. Il factory
SignatureException::tsaUrlEmpty()produce questo messaggio. Si tratta di un difetto di configurazione, non di un errore di rete. - Soluzione.
- Impostare un URL dell’endpoint non vuoto sul client dell’autorità di marca temporale, ad esempio
https://timestamp.example.com/tsa. - Se il livello richiesto non richiede la marca temporale, rimuovere invece il collegamento del client dell’autorità di marca temporale.
- Rieseguire la chiamata.
- Impostare un URL dell’endpoint non vuoto sul client dell’autorità di marca temporale, ad esempio
- Correlato. Riferimento delle eccezioni.
Voce: la marca temporale della firma non vincola la firma (impronta non corrispondente)
Sezione intitolata “Voce: la marca temporale della firma non vincola la firma (impronta non corrispondente)”- Sintomo.
TsaTokenVerificationExceptionche riporta il passoStep::ImprintBinding, con una terminazione del messaggio comeTSTInfo messageImprint does not bind the SignerInfo signature value— il token appone la marca temporale su byte diversi da quelli della firma che afferma di coprire. - Causa probabile. L’impronta del messaggio della marca temporale della firma non è l’hash del valore di firma SignerInfo a cui è associata. La causa benigna più comune è un documento prodotto da una versione di NextPDF precedente alla correzione del vincolo dell’impronta secondo RFC 3161 Appendix A: quelle versioni calcolavano l’hash di un input diverso, quindi le loro marche temporali B-T non possono dimostrare il vincolo a un verificatore rigoroso. Altre cause sono un token di marca temporale scambiato o manomesso, oppure un token la cui impronta usa SHA-1 o un algoritmo non riconosciuto (rifiutato in modalità fail-closed per questo controllo).
- Evidenza / diagnosi. Il controllo è il passo dedicato
verifySignatureTimestamp()(Step::ImprintBinding), che riceve il valore di firma come input obbligatorio, così da non poter mai essere saltato silenziosamente. Adotta il fail-closed in caso di input vuoto, di un identificatore di oggetto dell’impronta non riconosciuto, di un’impronta SHA-1, di una forma di impronta malformata o di una discrepanza di hash. - Soluzione.
- Se il documento è stato prodotto da una versione del motore precedente alla correzione, rifirmarlo e riapporvi la marca temporale con una versione attuale. L’impronta di una marca temporale è una prova immutabile e non può essere riparata sul posto. Si tratta di una modifica incompatibile intenzionale e permanente (vedere la voce “Security” del CHANGELOG relativa alla correzione di conformità del messageImprint della marca temporale di firma PAdES).
- Se il documento è attuale, trattare la discrepanza come un autentico errore di vincolo: la marca temporale non copre questa firma, quindi non farvi affidamento per B-T.
- Per un algoritmo di impronta SHA-1 o sconosciuto, la marca temporale non può dimostrare il vincolo indipendentemente dall’età; ottenere una marca temporale che usi un digest di impronta supportato (SHA-256 per impostazione predefinita).
- Correlato. Riferimento delle eccezioni.
Voce: il segnaposto della firma è assente dal buffer
Sezione intitolata “Voce: il segnaposto della firma è assente dal buffer”- Sintomo.
SignatureExceptioncon la terminazioneno /Contents <…> field found in PDF buffer (signature placeholder missing). - Causa probabile. La fase di firma è stata eseguita su un buffer privo di un contenitore di firma riservato, quindi non esiste alcuno spazio in cui scrivere la firma.
- Evidenza / diagnosi. Il factory
SignatureException::signatureContentsNotFound()produce questo messaggio. - Soluzione.
- Assicurarsi che il campo della firma e il relativo segnaposto siano scritti prima dell’esecuzione della fase di firma.
- Rieseguire la pipeline in modo che il segnaposto esista all’avvio della firma.
- Correlato. Riferimento delle eccezioni.
Voce: lo stato di revoca è sconosciuto (responder OCSP ha rifiutato)
Sezione intitolata “Voce: lo stato di revoca è sconosciuto (responder OCSP ha rifiutato)”- Sintomo.
SignatureExceptioncon la terminazioneOCSP responder returned non-successful OCSPResponseStatus "<status>". - Causa probabile. Il responder OCSP non ha restituito uno stato
successful, quindi non ha prodotto alcuna asserzione di revoca. Il motore segue RFC 6960 §4.2.1, che cita nel sorgente: un corpo di risposta popolato è consentito solo per lo statosuccessful (0). Il motore rifiuta di trattare una risposta rifiutata come un risultato di attendibilità positiva. - Evidenza / diagnosi. Il factory
SignatureException::nonSuccessfulOcspResponseStatus()produce questo messaggio e indica lo stato segnalato, ad esempiotryLaterointernalError. Un byte di stato riservato o sconosciuto produce inveceSignatureException::reservedOcspResponseStatus(). - Soluzione.
- Individuare lo stato nel messaggio. Per uno stato transitorio come
tryLater, riprovare più tardi il recupero delle informazioni di revoca. - Per
unauthorizedomalformedRequest, verificare l’URL della richiesta OCSP e il certificato atteso dal responder. - Non sopprimere l’errore per ottenere un artefatto B-LT o B-LTA; l’asserzione di revoca fa parte di quel livello.
- Individuare lo stato nel messaggio. Per uno stato transitorio come
- Correlato. Riferimento delle eccezioni.
Voce: una voce della catena di certificati non viene decodificata
Sezione intitolata “Voce: una voce della catena di certificati non viene decodificata”- Sintomo.
SignatureExceptioncon la terminazionefailed to base64-decode PEM body — input is not valid PEM. - Causa probabile. Una voce della catena di certificati non è un PEM valido — in genere per troncamento, un carattere estraneo o un blob DER binario fornito dove era atteso PEM.
- Evidenza / diagnosi. Il factory
SignatureException::pemDecodingFailed()produce questo messaggio durante l’assemblaggio della catena. - Soluzione.
- Esaminare ogni certificato della catena per individuare caratteri estranei o troncamenti.
- Riesportare il certificato interessato in forma PEM.
- Rieseguire la chiamata di firma.
- Correlato. Cifratura e autorizzazioni.
Voce: il tipo di chiave privata non corrisponde all’algoritmo
Sezione intitolata “Voce: il tipo di chiave privata non corrisponde all’algoritmo”- Sintomo.
SignatureExceptioncon la terminazioneexpected private key of type "<x>" for the configured algorithm but got "<y>". - Causa probabile. La chiave privata caricata non corrisponde all’algoritmo di firma configurato — ad esempio una chiave RSA con una selezione ECDSA.
- Evidenza / diagnosi. Il factory
SignatureException::unexpectedKeyType()produce questo messaggio e indica sia la classe di chiave attesa sia quella effettiva. - Soluzione.
- Verificare che la coppia certificato/chiave corrisponda all’algoritmo selezionato.
- Modificare la selezione dell’algoritmo in modo che corrisponda alla chiave, oppure caricare la chiave che corrisponde all’algoritmo.
- Rieseguire la chiamata di firma.
- Correlato. Riferimento delle eccezioni.
Voce: la chiave o il materiale di firma Ed25519 è malformato
Sezione intitolata “Voce: la chiave o il materiale di firma Ed25519 è malformato”- Sintomo.
SignatureExceptioncon una terminazione che indica una discrepanza di lunghezza Ed25519 — ad esempioEd25519 signature length <n> ≠ expected 64 bytes, oppureEd25519 round-trip self-verify failed. - Causa probabile. La build di crittografia del runtime ha restituito materiale di chiave o di firma di lunghezza errata, oppure una firma appena prodotta non è stata verificata rispetto alla propria chiave pubblica. Il motore cita RFC 8032 §3.4 nel sorgente, che fissa a 64 byte una firma Ed25519 detached. Il motore interrompe l’operazione anziché emettere materiale che non è in grado di autoverificare.
- Evidenza / diagnosi. I factory pertinenti sono
SignatureException::ed25519SignatureMalformed(),::ed25519RoundTripVerifyFailed(),::ed25519KeyParseFailed(),::ed25519SeedInvalid(),::ed25519SecretKeyMalformed()e::ed25519PublicKeyInvalid(). Ciascuno indica la lunghezza osservata. - Soluzione.
- Reinstallare l’estensione PHP libsodium; una build incompleta o danneggiata è la causa documentata del materiale di lunghezza errata.
- Verificare che la chiave sia una chiave Ed25519 e che OpenSSL sia 1.1.1 o più recente.
- Rieseguire la chiamata di firma.
- Correlato. Riferimento delle eccezioni.
Voce: il dizionario della marca temporale di archiviazione non è stato emesso
Sezione intitolata “Voce: il dizionario della marca temporale di archiviazione non è stato emesso”- Sintomo.
SignatureExceptioncon la terminazioneno /Type /DocTimeStamp dictionary was emitted into the PDF buffer. - Causa probabile. Il ciclo di archiviazione B-LTA è stato eseguito, ma il dizionario della marca temporale del documento non ha mai raggiunto il buffer; di conseguenza, l’artefatto risulterebbe un B-LTA scritto a metà. Il motore rifiuta di restituirlo.
- Evidenza / diagnosi. Il factory
SignatureException::documentTimestampNotEmitted()produce questo messaggio. È un errore di post-condizione sollevato durante la finalizzazione. - Soluzione.
- Considerare l’output come scartato; non distribuire l’artefatto parziale.
- Rieseguire la pipeline B-LTA con un’autorità di marca temporale raggiungibile.
- Se l’errore si ripete, acquisire
getContext()e l’eccezione precedente concatenata per una segnalazione di difetto.
- Correlato. Riferimento delle eccezioni.
Casi limite e insidie
Sezione intitolata “Casi limite e insidie”- Questi factory impostano
cert_infosu un subject o un’impronta digitale solo quando è disponibile; uncert_infovuoto è previsto per gli errori di capacità e di configurazione. - Una richiesta B-LT o B-LTA priva di un client HTTP configurato solleva
SignatureException::httpClientMissing()— il recupero delle informazioni di revoca richiede un client PSR-18 passato all’orchestrator. - Un certificato basato su HSM privo di un’implementazione del signer solleva
SignatureException::hsmSignerMissing(); collegare il signer al certificato prima della firma.
Vedere anche
Sezione intitolata “Vedere anche”Glossario: PAdES livello · asserzione di revoca