Salta ai contenuti

Risoluzione dei problemi: errori di firma 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. SignatureException con il messaggio terminante in nextpdf/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() restituisce signature_level impostato sul livello richiesto.
  • Soluzione.
    1. Installare il provider: eseguire composer require nextpdf/enterprise.
    2. Rieseguire la chiamata di firma.
    3. Se non è possibile installare il provider, richiedere invece B-B o B-T, prodotti dal pacchetto core.
  • 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. SignatureLevelUnreachableException con un messaggio nella forma PAdES 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() restituisce requestedLevel, highestAchievableLevel e reason. Il campo reason indica la lacuna infrastrutturale. Questa è l’impostazione predefinita fail-closed, introdotta per impedire che un documento dichiari un livello che non soddisfa.
  • Soluzione.
    1. Leggere il campo reason per individuare l’infrastruttura mancante.
    2. Fornire il componente mancante — ad esempio, configurare un’autorità di marca temporale — e rieseguire la chiamata.
    3. Per accettare intenzionalmente un livello inferiore, passare allowDegradation: true a PadesOrchestrator. La chiamata produce quindi highestAchievableLevel e segnala il livello effettivamente prodotto.
  • 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. SignatureException con la terminazione TSA 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 il signature_level richiesto.
  • Soluzione.
    1. Configurare un client dell’autorità di marca temporale e passarlo all’orchestrator.
    2. Rieseguire la chiamata.
    3. 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. SignatureException con la terminazione TSA 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.
    1. Impostare un URL dell’endpoint non vuoto sul client dell’autorità di marca temporale, ad esempio https://timestamp.example.com/tsa.
    2. Se il livello richiesto non richiede la marca temporale, rimuovere invece il collegamento del client dell’autorità di marca temporale.
    3. Rieseguire la chiamata.
  • Correlato. Riferimento delle eccezioni.

Voce: il segnaposto della firma è assente dal buffer

Sezione intitolata “Voce: il segnaposto della firma è assente dal buffer”
  • Sintomo. SignatureException con la terminazione no /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.
    1. Assicurarsi che il campo della firma e il relativo segnaposto siano scritti prima dell’esecuzione della fase di firma.
    2. 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. SignatureException con la terminazione OCSP 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 stato successful (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 esempio tryLater o internalError. Un byte di stato riservato o sconosciuto produce invece SignatureException::reservedOcspResponseStatus().
  • Soluzione.
    1. Individuare lo stato nel messaggio. Per uno stato transitorio come tryLater, riprovare più tardi il recupero delle informazioni di revoca.
    2. Per unauthorized o malformedRequest, verificare l’URL della richiesta OCSP e il certificato atteso dal responder.
    3. Non sopprimere l’errore per ottenere un artefatto B-LT o B-LTA; l’asserzione di revoca fa parte di quel livello.
  • 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. SignatureException con la terminazione failed 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.
    1. Esaminare ogni certificato della catena per individuare caratteri estranei o troncamenti.
    2. Riesportare il certificato interessato in forma PEM.
    3. 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. SignatureException con la terminazione expected 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.
    1. Verificare che la coppia certificato/chiave corrisponda all’algoritmo selezionato.
    2. Modificare la selezione dell’algoritmo in modo che corrisponda alla chiave, oppure caricare la chiave che corrisponde all’algoritmo.
    3. 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. SignatureException con una terminazione che indica una discrepanza di lunghezza Ed25519 — ad esempio Ed25519 signature length <n> ≠ expected 64 bytes, oppure Ed25519 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.
    1. Reinstallare l’estensione PHP libsodium; una build incompleta o danneggiata è la causa documentata del materiale di lunghezza errata.
    2. Verificare che la chiave sia una chiave Ed25519 e che OpenSSL sia 1.1.1 o più recente.
    3. 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. SignatureException con la terminazione no /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.
    1. Considerare l’output come scartato; non distribuire l’artefatto parziale.
    2. Rieseguire la pipeline B-LTA con un’autorità di marca temporale raggiungibile.
    3. Se l’errore si ripete, acquisire getContext() e l’eccezione precedente concatenata per una segnalazione di difetto.
  • Correlato. Riferimento delle eccezioni.
  • Questi factory impostano cert_info su un subject o un’impronta digitale solo quando è disponibile; un cert_info vuoto è 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.

Glossario: PAdES livello · asserzione di revoca