Dépannage : échecs de signature et d'horodatage
Ces fiches couvrent les échecs de signature que le moteur lève via NextPDF\Exception\SignatureException et NextPDF\Security\Signature\Exception\SignatureLevelUnreachableException. Chaque fiche indique la méthode de fabrique ou la classe exacte, afin que tu puisses confirmer la cause à partir du message et de getContext() plutôt que de la déduire.
Remarque de formulation : le moteur ne certifie ni qu’une signature est valide ni qu’un document est protégé. Il signale l’échec détecté. Considère chaque résolution comme une étape destinée à supprimer une cause signalée.
Entrée : le niveau PAdES « B-LT » ou « B-LTA » ne peut pas être produit
Section intitulée « Entrée : le niveau PAdES « B-LT » ou « B-LTA » ne peut pas être produit »- Symptôme.
SignatureExceptiondont le message se termine parnextpdf/enterprise package is required for B-LT/B-LTA signatures. - Cause probable. Le fournisseur de la capacité de validation à long terme manque. B-LT et B-LTA intègrent le matériel de révocation et un horodatage d’archivage ; ce fournisseur est inclus dans
nextpdf/enterprise. - Preuve / diagnostic. La fabrique
SignatureException::ltvCapabilityMissing()produit ce message exact.getContext()renvoiesignature_levelavec le niveau que tu as tenté. - Résolution.
- Installe le fournisseur : exécute
composer require nextpdf/enterprise. - Réexécute l’appel de signature.
- Si tu ne peux pas installer le fournisseur, demande plutôt
B-BouB-T, que le paquet cœur sait produire.
- Installe le fournisseur : exécute
- Voir aussi. Référence des exceptions.
Entrée : le niveau de signature est inatteignable et l’appel est rejeté
Section intitulée « Entrée : le niveau de signature est inatteignable et l’appel est rejeté »- Symptôme.
SignatureLevelUnreachableExceptionavec un message de la formePAdES level "<x>" is unreachable (highest achievable: "<y>"). - Cause probable. Le niveau de conformité demandé requiert une infrastructure indisponible au moment de la signature — le plus souvent une autorité d’horodatage pour B-T et au-delà. Le moteur échoue en mode fermé : il ne rétrograde pas silencieusement pour annoncer ensuite le niveau supérieur.
- Preuve / diagnostic.
getContext()renvoierequestedLevel,highestAchievableLeveletreason. Le champreasonindique l’élément d’infrastructure manquant. C’est le comportement par défaut en mode fermé, introduit pour empêcher qu’un document revendique un niveau qu’il n’atteint pas. - Résolution.
- Lis le champ
reasonpour identifier l’infrastructure manquante. - Fournis le composant manquant — par exemple, configure une autorité d’horodatage — puis réexécute l’appel.
- Pour accepter délibérément un niveau inférieur, passe
allowDegradation: trueàPadesOrchestrator. L’appel produit alorshighestAchievableLevelet signale le niveau qu’il a réellement produit.
- Lis le champ
- Voir aussi. Chiffrement et permissions.
Entrée : le client de l’autorité d’horodatage est requis mais absent
Section intitulée « Entrée : le client de l’autorité d’horodatage est requis mais absent »- Symptôme.
SignatureExceptionse terminant parTSA client is required for level <x> but none was provided. - Cause probable. Une demande B-T, B-LT ou B-LTA requiert un client d’autorité d’horodatage, et aucun n’a été configuré dans l’orchestrateur.
- Preuve / diagnostic. La fabrique
SignatureException::tsaRequired()produit ce message ;getContext()contient lesignature_leveltenté. - Résolution.
- Configure un client d’autorité d’horodatage et passe-le à l’orchestrateur.
- Réexécute l’appel.
- Pour produire un niveau qui ne requiert pas d’horodatage, demande
B-B.
- Voir aussi. Référence des exceptions.
Entrée : l’URL du point de terminaison de l’autorité d’horodatage est vide
Section intitulée « Entrée : l’URL du point de terminaison de l’autorité d’horodatage est vide »- Symptôme.
SignatureExceptionse terminant parTSA endpoint URL is empty. - Cause probable. Un client d’autorité d’horodatage a été construit avec une URL de point de terminaison vide.
- Preuve / diagnostic. La fabrique
SignatureException::tsaUrlEmpty()produit ce message. Il s’agit d’un défaut de configuration, pas d’un échec réseau. - Résolution.
- Définis une URL de point de terminaison non vide pour le client d’autorité d’horodatage, par exemple
https://timestamp.example.com/tsa. - Si l’horodatage n’est pas requis pour le niveau demandé, retire plutôt le câblage du client d’autorité d’horodatage.
- Réexécute l’appel.
- Définis une URL de point de terminaison non vide pour le client d’autorité d’horodatage, par exemple
- Voir aussi. Référence des exceptions.
Entrée : l’espace réservé de signature est absent du tampon
Section intitulée « Entrée : l’espace réservé de signature est absent du tampon »- Symptôme.
SignatureExceptionse terminant parno /Contents <…> field found in PDF buffer (signature placeholder missing). - Cause probable. L’étape de signature s’est exécutée sur un tampon qui ne contient aucun conteneur de signature réservé ; il n’y a donc aucun emplacement où écrire la signature.
- Preuve / diagnostic. La fabrique
SignatureException::signatureContentsNotFound()produit ce message. - Résolution.
- Assure-toi que le champ de signature et son espace réservé sont écrits avant l’exécution de l’étape de signature.
- Réexécute le pipeline pour que l’espace réservé soit présent au démarrage de la signature.
- Voir aussi. Référence des exceptions.
Entrée : le statut de révocation est inconnu (le répondeur OCSP a refusé)
Section intitulée « Entrée : le statut de révocation est inconnu (le répondeur OCSP a refusé) »- Symptôme.
SignatureExceptionse terminant parOCSP responder returned non-successful OCSPResponseStatus "<status>". - Cause probable. Le répondeur OCSP n’a pas renvoyé de statut
successful; il n’a donc produit aucune assertion de révocation. Le moteur suit la RFC 6960 §4.2.1, citée dans le code source : un corps de réponse renseigné n’est autorisé que pour le statutsuccessful (0). Le moteur refuse de traiter une réponse refusée comme un résultat de confiance positif. - Preuve / diagnostic. La fabrique
SignatureException::nonSuccessfulOcspResponseStatus()produit ce message et indique le statut signalé, par exempletryLaterouinternalError. Un octet de statut réservé ou inconnu produit plutôtSignatureException::reservedOcspResponseStatus(). - Résolution.
- Identifie le statut dans le message. Pour un statut transitoire tel que
tryLater, réessaie la récupération de révocation plus tard. - Pour
unauthorizedoumalformedRequest, vérifie l’URL de la requête OCSP et le certificat attendu par le répondeur. - Ne masque pas l’échec d’obtention d’un artefact B-LT ou B-LTA ; l’assertion de révocation fait partie de ce niveau.
- Identifie le statut dans le message. Pour un statut transitoire tel que
- Voir aussi. Référence des exceptions.
Entrée : une entrée de la chaîne de certificats ne peut pas être décodée
Section intitulée « Entrée : une entrée de la chaîne de certificats ne peut pas être décodée »- Symptôme.
SignatureExceptionse terminant parfailed to base64-decode PEM body — input is not valid PEM. - Cause probable. Une entrée de la chaîne de certificats n’est pas un PEM valide — typiquement une troncature, un caractère parasite ou un blob DER binaire fourni là où un PEM était attendu.
- Preuve / diagnostic. La fabrique
SignatureException::pemDecodingFailed()produit ce message lors de l’assemblage de la chaîne. - Résolution.
- Inspecte chaque certificat de la chaîne à la recherche de caractères parasites ou d’une troncature.
- Réexporte le certificat concerné au format PEM.
- Réexécute l’appel de signature.
- Voir aussi. Chiffrement et permissions.
Entrée : le type de clé privée ne correspond pas à l’algorithme
Section intitulée « Entrée : le type de clé privée ne correspond pas à l’algorithme »- Symptôme.
SignatureExceptionse terminant parexpected private key of type "<x>" for the configured algorithm but got "<y>". - Cause probable. La clé privée chargée ne correspond pas à l’algorithme de signature configuré — par exemple une clé RSA avec une sélection ECDSA.
- Preuve / diagnostic. La fabrique
SignatureException::unexpectedKeyType()produit ce message et nomme la classe de clé attendue ainsi que la classe réelle. - Résolution.
- Vérifie que le certificat et la paire de clés correspondent à l’algorithme que tu as sélectionné.
- Change la sélection d’algorithme pour l’aligner sur la clé, ou charge la clé qui correspond à l’algorithme.
- Réexécute l’appel de signature.
- Voir aussi. Référence des exceptions.
Entrée : le matériel de clé ou de signature Ed25519 est malformé
Section intitulée « Entrée : le matériel de clé ou de signature Ed25519 est malformé »- Symptôme.
SignatureExceptiondont le message nomme une discordance de longueur Ed25519 — par exempleEd25519 signature length <n> ≠ expected 64 bytes, ouEd25519 round-trip self-verify failed. - Cause probable. La bibliothèque cryptographique compilée de l’environnement d’exécution a renvoyé du matériel de clé ou de signature d’une longueur incorrecte, ou une signature tout juste produite n’a pas pu être vérifiée avec sa propre clé publique. Le moteur cite la RFC 8032 §3.4 dans le code source, qui fixe une signature Ed25519 détachée à 64 octets. Le moteur s’interrompt plutôt que d’émettre du matériel qu’il ne peut pas vérifier lui-même.
- Preuve / diagnostic. Les fabriques concernées sont
SignatureException::ed25519SignatureMalformed(),::ed25519RoundTripVerifyFailed(),::ed25519KeyParseFailed(),::ed25519SeedInvalid(),::ed25519SecretKeyMalformed()et::ed25519PublicKeyInvalid(). Chacune indique la longueur observée. - Résolution.
- Réinstalle l’extension PHP libsodium ; une compilation tronquée ou corrompue est la cause documentée d’un matériel de longueur incorrecte.
- Confirme que la clé est une clé Ed25519 et qu’OpenSSL est en version 1.1.1 ou plus récente.
- Réexécute l’appel de signature.
- Voir aussi. Référence des exceptions.
Entrée : le dictionnaire d’horodatage d’archivage n’a pas été émis
Section intitulée « Entrée : le dictionnaire d’horodatage d’archivage n’a pas été émis »- Symptôme.
SignatureExceptionse terminant parno /Type /DocTimeStamp dictionary was emitted into the PDF buffer. - Cause probable. La boucle d’archivage B-LTA s’est exécutée, mais le dictionnaire d’horodatage du document n’a jamais été écrit dans le tampon, de sorte que l’artefact serait un B-LTA à moitié écrit. Le moteur refuse de le renvoyer.
- Preuve / diagnostic. La fabrique
SignatureException::documentTimestampNotEmitted()produit ce message. C’est un échec de postcondition levé au moment de la finalisation. - Résolution.
- Considère la sortie comme rejetée ; ne livre pas l’artefact partiel.
- Réexécute le pipeline B-LTA avec une autorité d’horodatage joignable.
- Si l’échec se répète, capture
getContext()et l’exception précédente chaînée pour un rapport de défaut.
- Voir aussi. Référence des exceptions.
Cas limites et pièges
Section intitulée « Cas limites et pièges »- Ces fabriques renseignent
cert_infoavec un sujet ou une empreinte uniquement lorsque cette information est disponible ; uncert_infovide est attendu pour les échecs de capacité et de configuration. - Une demande B-LT ou B-LTA sans client HTTP configuré lève
SignatureException::httpClientMissing()— la récupération de révocation a besoin d’un client PSR-18 fourni à l’orchestrateur. - Un certificat adossé à un HSM sans implémentation de signataire lève
SignatureException::hsmSignerMissing(); raccorde le signataire au certificat avant de signer.
Voir aussi
Section intitulée « Voir aussi »Glossaire : niveau PAdES · assertion de révocation