Skip to content

Troubleshooting: encryption and permission flags

Use these entries to troubleshoot decryption failures the engine raises through NextPDF\Exception\EncryptionException and NextPDF\Security\Exception\DecryptionFailedException, and to understand the boundary of Portable Document Format (PDF) permission flags.

Start with the boundary because it prevents the most common misconception: PDF permission flags in the encryption dictionary record the author’s intent. They are not an access-control mechanism enforced by this library. A reader that ignores the flags can still print, copy, or modify the content. Treat the flags as a request to a cooperating reader, not as enforcement.

  • Symptom. EncryptionException with a message of the form Encryption operation "<op>" failed using algorithm "<algorithm>".
  • Likely cause. The cipher operation could not run, typically because the OpenSSL extension is missing or misconfigured, the key material is invalid, or the initialization vector (IV) size is invalid at the cipher boundary.
  • Evidence / diagnosis. getContext() returns algorithm and operation. The operation value is one of encrypt, decrypt, or key_derivation, so you can identify which stage failed.
  • Resolution.
    1. Confirm that the OpenSSL PHP extension is installed and loaded.
    2. Use the operation field to find the failing stage.
    3. For key_derivation, verify the password or key inputs.
    4. Re-run the call.
  • Related. Exception reference.

Entry: decryption fails for a structural reason

Section titled “Entry: decryption fails for a structural reason”
  • Symptom. DecryptionFailedException with a message of the form Decryption failed for "<algorithm>": <reason>.
  • Likely cause. The ciphertext could not be processed for a non-tampering reason, such as truncated ciphertext, a missing IV, or the wrong key supplied at the application programming interface (API) boundary. The integrity check did not run because there was not enough material to evaluate.
  • Evidence / diagnosis. getContext() returns algorithm and reason. Source documentation distinguishes DecryptionFailedException from TamperedDataException: this exception means a configuration or transport error, not tampering. Do not treat it as a security incident on its own.
  • Resolution.
    1. Read reason to identify the structural defect, for example ciphertext shorter than IV+tag.
    2. Verify that the ciphertext was transported without truncation.
    3. Confirm that the key supplied at the boundary is the key used to encrypt the document.
    4. Re-run the call.
  • Related. Signature and timestamp failures.

Entry: a “tampered data” exception is raised

Section titled “Entry: a “tampered data” exception is raised”
  • Symptom. You receive NextPDF\Security\Exception\TamperedDataException rather than DecryptionFailedException.
  • Likely cause. The integrity check ran and failed. This differs from a structural decryption failure: enough material was present to evaluate integrity, and integrity did not hold.
  • Evidence / diagnosis. The source distinguishes the two classes: DecryptionFailedException is structural and not a security incident; TamperedDataException indicates that the authenticated content did not verify.
  • Resolution.
    1. Treat the input as untrusted; do not consume the decrypted content.
    2. Re-fetch the document from a trusted source.
    3. If the failure persists with a known-good source, capture getContext() for an incident report.
  • Related. Signature and timestamp failures.

Entry: permission flags are not stopping a downstream action

Section titled “Entry: permission flags are not stopping a downstream action”
  • Symptom. A document was produced with permission flags set — for example, copy or print disallowed — but a reader still copies or prints the content.
  • Likely cause. This is the expected boundary, not a defect. The permission integer passed to the core encryption dictionary builder is not applied as enforcement by this library. The flags are advisory metadata; a reader that does not honor them is not blocked by NextPDF.
  • Evidence / diagnosis. src/Security/Encryption/EncryptionDictionaryBuilder.php declares buildDict(int $permissions, string $fileId), and documents the parameter as ignored; retained for forward compatibility. The method begins unset($permissions, $fileId). The permission flags surfaced by src/Inspect/PdfPermissions.php are read-only inspection fields, not an enforcement layer.
  • Resolution.
    1. Do not rely on permission flags to stop printing, copying, or modification. They cannot be enforced by a producer library.
    2. Where you must restrict access, control distribution of the file itself, or apply an access-control system outside the PDF.
    3. Use PdfPermissions only to report the flags an existing document declares, not to assert that those actions are prevented.
  • Related. Signature and timestamp failures.
  • Symptom. NextPDF\Security\Exception\IncompatiblePdfAModeException when a build enables PDF/A and requests encryption.
  • Likely cause. The PDF/A profile forbids the Encrypt key in the trailer. The engine refuses the combination in either call order.
  • Evidence / diagnosis. See the PDF/A and PDF/UA entry for the cited clause, getContext() fields, and failure-path test.
  • Resolution.
    1. Decide whether the document needs archival conformance or encryption.
    2. Remove the call for the property you do not need.
    3. Re-run the pipeline.
  • Related. PDF/A and PDF/UA validation.
  • DecryptionFailedException and TamperedDataException mean different things: structural failure versus failed integrity. Branch on the class, not on the message.
  • The core encryption dictionary builder ignores the permission integer; any build that depends on permission enforcement from the core package is built on a misconception.
  • PdfPermissions is populated only for encrypted documents at full inspection depth and reflects the declared flags. A populated field does not mean the action is prevented.

Glossary: permission flags · authenticated decryption