Security and signing errors
At a glance
Section titled “At a glance”This page documents the security-domain exceptions in the NextPDF\Security
namespace tree. Each entry names the class, states when it is thrown, lists the
fields its getContext() returns, and gives a recovery step.
Most of these classes extend SecurityException, which extends NextPdfException
and implements ContextAwareExceptionInterface. That means getContext(): array
returns structured, secret-free diagnostics you can route to logging or
application performance monitoring (APM) pipelines. Catch SecurityException to
trap every security-domain failure in one block; catch a specific subclass when
you need its typed payload.
A few classes in this tree extend RuntimeException directly rather than
SecurityException. Those are marked below; they do not expose getContext(),
and most are documented as internal control-flow signals you should not expect to
catch in application code.
Context-field convention
Section titled “Context-field convention”| Aspect | Behavior |
|---|---|
| Base contract | NextPdfException::getContext() returns []; subclasses override it. |
| Secret hygiene | Messages and context omit raw key material, plaintext, PINs, and initialization vector (IV) bytes. Keys are surfaced only as a fingerprint prefix. |
SecurityException | Abstract base; carries no fields of its own. Subclasses define the payload. |
Base type
Section titled “Base type”SecurityException
Section titled “SecurityException”- When thrown. Never thrown directly; it is the abstract base for the
security domain. It exists so a single
catch (SecurityException $e)block can trap authenticated-encryption integrity failures, nonce-reuse defenses, the PDF/A-versus-encryption binding, key-management faults, and PKI failures. - Context fields. None of its own. Inherits the empty default from
NextPdfException; subclasses populate the payload. - Recovery. Catch the concrete subclass for actionable handling, or
SecurityExceptionfor coarse security-incident routing.
Encryption and authenticated-encryption errors
Section titled “Encryption and authenticated-encryption errors”These are raised by the AES-GCM (Galois/Counter Mode) encryptor and the PDF/A guard. For symptom-first guidance, see Encryption and permissions.
DecryptionFailedException
Section titled “DecryptionFailedException”- When thrown. An authenticated-encryption with associated data (AEAD) decryption fails for a non-tampering reason: truncated ciphertext, a missing IV, or a wrong key supplied at the API boundary, where there was not enough material for the integrity check to actually run. This is a configuration or transport error, not a security incident.
- Context fields.
algorithm(for exampleAES-256-GCM),reason(for exampleciphertext shorter than IV+tag). - Recovery. Verify the ciphertext, IV, and key are complete and correctly
framed; do not treat this as tampering. Contrast with
TamperedDataException.
TamperedDataException
Section titled “TamperedDataException”- When thrown. The AEAD authentication tag fails verification. The tag covers
ciphertext plus associated authenticated data (AAD); if either was modified
after encryption, the underlying
openssl_decrypt()returnsfalse. This distinct subtype lets you surface a security-incident-grade alert rather than a framing error. - Context fields.
algorithm,ciphertext_length(length of the rejected ciphertext, excluding IV and tag). - Recovery. Treat as tampering or a wrong key/IV. Do not retry blindly; investigate the source of the ciphertext. Per ISO/TS 32003:2023 §5.2 and NIST SP 800-38D §6.5, a failed tag check means the data is not authentic.
NonceReuseException
Section titled “NonceReuseException”- When thrown. AES-GCM is asked to encrypt twice with the same key and IV pair. The encryptor defends with a per-instance monotonic counter and, as defense in depth, a runtime hash-set of every emitted (key-fingerprint, IV) pair. Because the counter rules out collisions by construction, this firing is a critical-priority bug indicator that must never occur in production. Reusing a key/IV pair compromises the entire keystream (ISO/TS 32003:2023 §5.2 NOTE 2; NIST SP 800-38D §8.3).
- Context fields.
key_fingerprint_prefix(first 8 hex chars of SHA-256(key)),iv_length(always 12 for ISO/TS 32003),reason(hashset-collisionorcounter-rollover, distinguishing a counter-defeating refactor bug from the 2^63 counter trip-wire), andiv_fixed_field_hex(the IV fixed field, present only when supplied, reported under its own key and never mislabeled as the key fingerprint). - Recovery. Abort immediately and rotate the key. File a defect report; this indicates a bug in the encryptor, not bad caller input.
GcmInvocationLimitExceededException
Section titled “GcmInvocationLimitExceededException”- When thrown. An opt-in NIST SP 800-38D §8.3 safety-of-use invocation count
is reached for a given AES-GCM key. This is a defense-in-depth telemetry hook
for callers that want to enforce the spec-recommended bound (around 2^32
invocations per key) earlier than the architectural limits inside the
encryptor. It does not fire by default; only the
assertWithinSafetyBound()helper raises it. - Context fields.
key_fingerprint_prefix,invocation_count(currentencrypt()count, at or above the limit),invocation_limit(the opt-in bound). - Recovery. Rotate the document key (construct a fresh encryptor with new key material) before the cumulative collision and forgery probability stops being negligible, or expand caller policy to refuse continued service.
IncompatiblePdfAModeException
Section titled “IncompatiblePdfAModeException”- When thrown. An encryption operation is attempted on a PDF/A-tagged
document. The PDF/A family (PDF/A-2, PDF/A-3, PDF/A-4) uniformly forbids
encryption: per ISO 19005 §6.1.3 the
Encryptkey shall not be present in the trailer, and ISO 19005-4:2020 Annexes A and B inherit this without modification. There is no permitted combination of PDF/A and encryption. - Context fields.
pdfa_mode(for examplepdfa4,pdfa3),encryption_operation(the rejected call, for exampleuseAesGcm). - Recovery. To produce an encrypted document, omit the
enablePdfA()call; to produce an archival document, omit the encryption call. See PDF/A and PDF/UA validation.
Crypto-policy enforcement
Section titled “Crypto-policy enforcement”CryptoPolicyViolationException
Section titled “CryptoPolicyViolationException”- When thrown. A configured crypto policy rejects an algorithm, key strength,
or cipher selected by a core signing, encryption, or hashing operation. It is
the fail-closed boundary for compliance enforcement (for example FIPS 140-2/3,
eIDAS, or custom enterprise policy) and is raised by
CryptoPolicyEnforcerbefore any signature or ciphertext is produced, so a policy-violating operation can never emit a non-approved artifact. Distinct from a narrow OpenSSL operation failure and from a signing-primitive failure: this is a policy rejection of an otherwise valid request. Aligned with NIST SP 800-131A Rev. 2 and ISO/IEC 19790:2025 §7. - Context fields.
policy(policy name, for exampleFIPS 140-3 Strict),category(hash,signature,encryption, orkey-strength),item(the rejected item, for example an object identifier (OID), cipher name, orrsa/1024),reason. - Recovery. Select an algorithm, key length, or cipher that the named policy approves, or adjust the policy if you own it. Route the structured context to the documented compliance runbook.
Key management
Section titled “Key management”Two same-named classes exist. They share the SecurityException root so one
catch (SecurityException $e) block traps both, but they carry distinct payloads.
Import by the fully qualified name when you need a specific shape.
KeyManagementException (lifecycle: NextPDF\Security\Exception)
Section titled “KeyManagementException (lifecycle: NextPDF\Security\Exception)”- When thrown. A key-management operation fails before the key is consumed by a sign or encrypt primitive: Privacy-Enhanced Mail (PEM), PKCS#12, or PKCS#11 key parse failures; key-derivation (HKDF, PBKDF2, scrypt) failures; AES Key Wrap (RFC 3394) rejection on a wrong key-encryption key; a hardware security module (HSM) returning malformed Distinguished Encoding Rules (DER); or an Ed25519 seed length mismatch.
- Context fields.
operation(for exampleload_pem,kek_derive,key_wrap),key_type(for exampleRSA,EC-P256,Ed25519,AES-256),reason. Raw key material is never included. - Recovery. Inspect the named operation and key type, fix the source key material or derivation input, and retry.
KeyManagementException (signing path: NextPDF\Security\Signature\Exception)
Section titled “KeyManagementException (signing path: NextPDF\Security\Signature\Exception)”- When thrown. A signer provider hits a key-management fault: the requested
key version is unknown, disabled, scheduled for destruction, lacks signing
permission, or is otherwise unusable. This is what
RsaPssSignerandLocalKeySignerProviderthrow on live key failures. Named constructors:unknownKeyVersion()andkeyVersionDisabled(). - Context fields.
providerId,keyVersion,reason. Accessors:providerId(),keyVersion(),reason(). - Recovery. Rotate or re-permission the key, or select a usable key version,
then retry. Distinct from
SignatureFailedException, which signals that the signing primitive itself failed.
Signing
Section titled “Signing”For symptom-first guidance on unreachable levels and missing capabilities, see Signature and timestamp failures.
SignatureFailedException (R4-13: NextPDF\Security\Exception)
Section titled “SignatureFailedException (R4-13: NextPDF\Security\Exception)”- When thrown. A cryptographic signing operation fails: an RSA, ECDSA, or
Ed25519 sign primitive returns
falseor wrong-length output; an HSM or PKCS#11 token responds with a non-success status; Cryptographic Message Syntax (CMS)SignedDataassembly fails on a malformed certificate or chain; or an Ed25519 round-trip self-verify fails. New code should prefer this R4-13 subtype over the legacy PAdES-coupled signature exception. - Context fields.
operation(for examplesign,verify,build_cms),algorithm(for examplersa-pkcs1v15-sha256,ed25519),reason. Accessors:getOperation(),getAlgorithm(),getReason(). - Recovery. Read the operation and algorithm, correct the input (key, certificate chain, or backend availability), and retry. Aligned with the fail-closed key-handling posture of ETSI EN 319 142-1.
SignatureFailedException (SPI: NextPDF\Security\Signature\Exception)
Section titled “SignatureFailedException (SPI: NextPDF\Security\Signature\Exception)”- When thrown. A
SignerProviderInterfaceimplementation cannot complete a signing operation for any reason not categorized as key-management: backend driver error, malformed key material, or unrecoverable HSM I/O. This is the catch-all for the fail-closed signing contract, where every primitive throws on failure rather than returningnull,false, or an empty string. Named constructor:forProvider(). - Context fields.
providerId,reason. Accessors:providerId(),reason(). - Recovery. Inspect the provider id and reason, fix the provider backend or
key material, and retry. Branch on
KeyManagementExceptionversus this type to separate “the key is bad” from “the primitive failed”.
SignatureLevelUnreachableException
Section titled “SignatureLevelUnreachableException”- When thrown. The requested PAdES conformance level cannot be honored under
the current runtime infrastructure (most often a missing timestamp authority for
B-T and above) and the caller has not granted permission to degrade. The default
is fail-closed: the engine refuses rather than silently producing a lower level
while advertising the higher one, which would be an eIDAS-grade regression.
Aligned with ETSI EN 319 142-1 §6. Note this class extends
NextPdfExceptiondirectly (notSecurityException). - Context fields.
requestedLevel,highestAchievableLevel,reason. Accessors:requestedLevel(),highestAchievableLevel(),reason(). - Recovery. Read
reasonto identify the missing infrastructure and supply it (for example configure a timestamp authority), or passallowDegradation: truetoPadesOrchestratorto intentionally accept the highest achievable level.
SignerProviderNotFoundException
Section titled “SignerProviderNotFoundException”- When thrown.
SignerProviderRegistry::get()is asked for a provider id that is not registered. Implements PSR-11NotFoundExceptionInterface, so the registry conforms to the PSR-11 container contract. Named constructor:forId(). This class extendsRuntimeExceptionand does not exposegetContext(). - Context fields. None. The unregistered id appears in the message.
- Recovery. Register the provider under the expected id before requesting it, or correct the id you pass to the registry.
Hashing (SHAKE256)
Section titled “Hashing (SHAKE256)”These extend RuntimeException and do not expose getContext(). SHAKE256 is the
SHA-3 extendable-output function required by some ISO/TS 32001 paths.
Shake256NotAvailableException
Section titled “Shake256NotAvailableException”- When thrown. At digest time, when the selected provider cannot satisfy the
request. Named constructors:
noBackend()(no working SHAKE256 backend on this host, across all attempted tiers) andffiCallFailed()(an FFI-bound OpenSSL EVP call returned a non-success status, for example from a stripped libcrypto build). - Context fields. None. The message names the attempted tiers or the failed symbol.
- Recovery. Install
ext-ffiwith OpenSSL 3.x present, or upgrade to a PHP build that exposesshake256inhash_algos(). A userland Keccak fallback is intentionally not shipped.
Shake256ProviderNotAvailableException
Section titled “Shake256ProviderNotAvailableException”- When thrown. From a SHAKE256 provider constructor when the capability probe
fails, so the provider cannot be instantiated. It is a control-flow signal: the
provider registry catches it, records the tier label, and tries the next tier.
It should never escape into application code. Named constructor:
forTier(). - Context fields. None. The message names the tier and reason.
- Recovery. Not caller-actionable directly; if the entire tier chain is
exhausted, the registry surfaces
Shake256NotAvailableException::noBackend()instead, which carries the operator-facing fix.
Document MAC integrity (ISO/TS 32004)
Section titled “Document MAC integrity (ISO/TS 32004)”These cover the ISO/TS 32004 document-level message authentication code (MAC),
stored under /AuthCode. Both extend NextPdfException and override
getContext().
DocumentMacTokenException
Section titled “DocumentMacTokenException”- When thrown. Fail-closed, by the MAC token reader, when a CMS
AuthenticatedDataMAC token is structurally malformed or declares an algorithm outside the agreed ISO/TS 32004 set. Named constructors:malformed()andalgorithmMismatch(). Marked@internal. - Context fields.
status(theDocumentMacVerificationStatusvalue, eitherMalformedTokenorAlgorithmMismatch). Public readonly property:$status. - Recovery. Treat the document as not verified. A malformed token or an algorithm outside the agreed set means the MAC cannot establish trust; do not proceed as if the content is protected.
DocumentMacVerificationException
Section titled “DocumentMacVerificationException”- When thrown. Fail-closed, when a document-level MAC verification cannot reach
a trusted state: a missing or malformed
/AuthCode, an algorithm outside the agreed set, an unwrap failure, or a MAC mismatch (tamper). The verifier’sverify()returns an explicit result for branching; this is the exception-flow counterpart thrown byassertVerified()so “trust the content” code can never proceed past an unverified document. Named constructor:fromResult(). - Context fields.
status(theDocumentMacVerificationStatusvalue). Public readonly property:$status. - Recovery. Do not trust the document content. Inspect
statusto distinguish a tamper (MAC mismatch) from a configuration issue (missing or malformed/AuthCode, algorithm mismatch).
PKI path validation (RFC 5280)
Section titled “PKI path validation (RFC 5280)”These cover RFC 5280 certification-path validation. The base type and its subclasses are fail-closed.
PkiPathValidationException
Section titled “PkiPathValidationException”- When thrown. A strict-mode failure from the RFC 5280 path validator. It is
the non-final base for narrower subclasses (
ChainLengthExceededException,UnsupportedExtensionException), so handlers that catch this type also catch those via Liskov substitution. ExtendsSecurityException. - Context fields. Does not override
getContext()(inherits the empty default). Carries the structured reasons in the frozen public readonly array property$reasons(a non-empty list of rule-name plus description strings). - Recovery. Read
$reasonsto identify the failing rule, fix the certificate chain, and re-validate. Catch this type to handle any path-validation failure uniformly.
ChainLengthExceededException
Section titled “ChainLengthExceededException”- When thrown. The path validator is asked to walk a chain whose length
exceeds the configured ceiling. The cap is enforced before any parsing begins,
so a malicious supplier cannot drive the validator into quadratic work or
exhaust resources with an arbitrarily deep chain. The default ceiling of 10
follows the PKIX-CMP profile (RFC 4210 §5.3.18); real-world chains fit in 5 to 6
entries. Subclass of
PkiPathValidationException. - Context fields. Inherits the empty
getContext(); the reason stringchain_length_exceeded: supplied=<n> cap=<n>is forwarded into the parent’s$reasons. Public readonly properties:$supplied,$cap. - Recovery. Supply a chain within the ceiling, or raise the configured cap if a legitimately longer chain is expected.
UnsupportedExtensionException
Section titled “UnsupportedExtensionException”- When thrown. The path validator encounters a critical X.509 extension whose
enforcement is not yet implemented. Per RFC 5280 §4.2, an unrecognized critical
extension must fail closed; both strict and lenient modes fail closed here, since
silently skipping a critical extension would be a security regression. The
validator covers chain build, AKI/SKI matching, key usage, extended key usage,
basic constraints, expiry, and signature verification; anything else critical
surfaces here. Subclass of
PkiPathValidationException. - Context fields. Inherits the empty
getContext(); structured reasons are forwarded into the parent’s$reasons. Public readonly properties:$extensionOid(dotted OID, for example2.5.29.30for name constraints),$extensionName,$clauseRef(pointer to the RFC 5280 clause and the deferred-items log entry). - Recovery. In lenient mode, catch this specific subclass to fall back to a
coarser policy without swallowing real path-validation failures. Audit
$extensionOidand$clauseRefagainst your PKI fixtures to see which extension is blocking validation.
RevocationCheckFailedException
Section titled “RevocationCheckFailedException”- When thrown. Both OCSP and certificate revocation list (CRL) endpoints are
exhausted without a definitive verdict: OCSP transport failure or malformed
response, and CRL transport failure or malformed CRL, with both circuit breakers
open or both caches missing. Strict mode treats this as fail-closed; lenient mode
catches it and emits a PSR-3 warning with
revocation = null. ExtendsSecurityException. - Context fields. Does not override
getContext()(inherits the empty default). Carries state in the public readonly properties$ocspStateand$crlState(each defaults tounknown). - Recovery. Restore reachability to a revocation source, wait for circuit breakers to close, or warm the cache, then retry. Do not suppress this to obtain a long-term-validation artifact; the revocation assertion is part of that level.
OCSP signature verification (RFC 6960)
Section titled “OCSP signature verification (RFC 6960)”OcspSignatureInvalidException
Section titled “OcspSignatureInvalidException”- When thrown. An RFC 6960 §4.2.2.2
BasicOCSPResponsesignature fails cryptographic verification against the responder’s certificate. The parser decodessignatureAlgorithm(RSA-PSS, ECDSA, or RSA-PKCS1v15) and verifiessignatureovertbsResponseData; any failure raises this typed exception so callers can distinguish a structurally valid but cryptographically tampered response from a malformed-DER response. Non-final, so downstream packages can publish more specific subclasses. ExtendsSecurityException. - Context fields. Does not override
getContext()(inherits the empty default). Carries the failure tag in the public readonly property$reason(for examplesignature_mismatch,responder_cert_not_in_bundle,unsupported_signature_algorithm); free-textdetailis folded into the message. - Recovery. Inspect
$reason. Forresponder_cert_not_in_bundle, supply the correct trust anchor bundle and responder certificate. Forsignature_mismatch, treat the response as untrustworthy. See Signature and timestamp failures.
Timestamping (RFC 3161)
Section titled “Timestamping (RFC 3161)”TsaException
Section titled “TsaException”- When thrown. A failure in RFC 3161 time-stamp authority (TSA) communication
or response parsing: the TSA returns an error status, the HTTP request fails, or
the ASN.1 response cannot be parsed. It is the base of the TSA fault hierarchy
and is non-final so verification failures can extend it. Extends
NextPdfException. - Context fields. Does not override
getContext()(inherits the empty default). - Recovery. Catch
TsaExceptionfor any TSA-fault path. Verify TSA reachability and that the endpoint returns a well-formed RFC 3161 response.
TsaTokenVerificationException
Section titled “TsaTokenVerificationException”- When thrown. CMS verification of an RFC 3161
TimeStampTokenfails at any of the mandated verification steps: RFC 5816 §3 ESSCertIDv2 binding, RFC 5652 §11 signed-attributes integrity, RFC 3161 §2.4.2producedAtfreshness, or RFC 5652 §5.4SignerInfosignature. Fail-closed, with a typed step discriminator so audit pipelines can tell replay from clock skew from cert-mismatch without grepping messages. Subclass ofTsaException, so legacycatch (TsaException)handlers continue to fire. - Context fields.
step(the failing pipelineStepvalue) andmessage. Accessor:getStep(). - Recovery. Actionable by a developer (misconfigured TSA certificate or skew
tolerance) or security (suspected MITM or replay). Read
stepto localize the failing stage and fix the corresponding input or trust configuration.
MalformedDerException
Section titled “MalformedDerException”- When thrown. Internal signal that a DER walk hit a malformed or truncated
boundary, raised by the low-level walkers inside the TSA token verifier. It is
always caught at the public verify boundary and re-wrapped into a
TsaTokenVerificationExceptioncarrying the proper step discriminator; it never leaks to caller code. ExtendsRuntimeException; marked@internal. - Context fields. None.
- Recovery. Not caller-facing. Handle the wrapped
TsaTokenVerificationExceptioninstead.
Certificate-extension decoding
Section titled “Certificate-extension decoding”These extend RuntimeException and do not expose getContext(). Both are
fail-closed decoders.
NameConstraintsDecodeException
Section titled “NameConstraintsDecodeException”- When thrown. The name-constraints decoder encounters an enforceable
GeneralSubtreeelement it cannot faithfully decode. RFC 5280 §4.2.1.10 requires a relying party to process an enforceable name constraint or reject the certificate; converting the prior silent drop into this typed failure prevents a fail-open that would have silently widened the accepted name set. Scope is limited to the enforceable name forms (directoryName, dNSName, iPAddress, rfc822Name, uniformResourceIdentifier); non-enforceable forms remain ignorable and never raise it. Named constructor:undecodableEnforceableBase(). Marked@internal. - Context fields. None. A log-safe detail string is carried in the message.
- Recovery. The enforcer surfaces a fail-closed
name_constraints:reason and the chain is rejected. Investigate the certificate’s name-constraints encoding; do not relax enforcement.
QcStatementsDecodeException
Section titled “QcStatementsDecodeException”- When thrown. The
qcStatementsextension is structurally malformed: truncated DER, a wrong tag, or a length overflow. The decoder is fail-closed and raises rather than returning a partial or heuristic result when it cannot determine with certainty what the extension says. Marked@api. - Context fields. None.
- Recovery. Catch it explicitly only if you intend to tolerate malformed encoding; otherwise treat the certificate’s qualified-certificate statements as undeterminable and reject or re-issue the certificate.
PKCS#11 sessions
Section titled “PKCS#11 sessions”Pkcs11SessionException
Section titled “Pkcs11SessionException”- When thrown. A PKCS#11 v3.1 session-management defect. Every named
constructor maps to a specific defect class and to a PKCS#11
CKR_*return value, exposed through the typed$kinddiscriminator so callers branch on a stable enum-string instead of fragile message matching. Constructors include:cryptokiNotInitialized(),userNotLoggedIn(),userAlreadyLoggedIn(),operationNotInitialized(),operationActive(),mechanismNotAllowed(),tokenDisconnected(),concurrentSessionLimitExceeded(),sessionAlreadyClosed(),stateTransitionInvalid(),osLockingRequired(),loginTtlExpired(), andsignOperationTtlExpired(). ExtendsSecurityException. - Context fields. Does not override
getContext()(inherits the empty default). Carries the typed kind in the public readonly property$kind, one of theKIND_*constants (for exampleKIND_USER_NOT_LOGGED_IN,KIND_TOKEN_DISCONNECTED,KIND_LOGIN_TTL_EXPIRED). Slot and session identifiers, mechanism, and TTL values appear in the message. PINs and certificate bytes are never included. - Recovery. Switch on
$kind. Foruser_not_logged_in, log in with the user PIN before initializing a sign operation. Fortoken_disconnected, treat all sessions on the slot as orphaned. For the TTL kinds, re-authenticate or re-initialize the operation. Formechanism_not_allowed, extend the configured mechanism allow-list or pick an allowed mechanism.