跳转到内容

疑难解答:加密与权限标志

本页条目涵盖引擎通过 NextPDF\Exception\EncryptionExceptionNextPDF\Security\Exception\DecryptionFailedException 抛出的解密失败,以及 PDF 权限标志的边界。

先说明边界,这能避免最常见的误解:加密字典中的 PDF 权限标志只记录作者的意图。它们并不是由本库强制执行的访问控制机制。忽略这些标志的阅读器(reader)仍然可以打印、复制或修改内容。请将这些标志视为向配合的阅读器提出的请求,而非强制手段。

  • 症状。 抛出 EncryptionException,消息形式为 Encryption operation "<op>" failed using algorithm "<algorithm>"
  • 可能原因。 密码运算无法执行,通常是因为 OpenSSL 扩展缺失或配置错误、密钥素材无效,或在加密边界处 IV 长度不正确。
  • 证据/诊断。 getContext() 会返回 algorithmoperationoperation 的值是 encryptdecryptkey_derivation 之一,可用于定位失败阶段。
  • 解法。
    1. 确认已安装并加载 OpenSSL PHP 扩展。
    2. 读取 operation 字段以定位失败阶段。
    3. 若为 key_derivation,请验证密码或密钥输入。
    4. 重新执行该调用。
  • 相关。 异常参考
  • 症状。 抛出 DecryptionFailedException,消息形式为 Decryption failed for "<algorithm>": <reason>
  • 可能原因。 密文因非篡改原因而无法处理,例如密文被截断、缺少 IV,或在 API 边界处提供了错误的密钥。由于可供评估的素材不足,完整性检查并未执行。
  • 证据/诊断。 getContext() 会返回 algorithmreason。源码将 DecryptionFailedException 记载为区别于 TamperedDataException:这个异常表示配置或传输错误,并非篡改迹象。不要单凭它就视为安全事件。
  • 解法。
    1. 读取 reason 以识别结构性缺陷,例如 ciphertext shorter than IV+tag
    2. 确认密文在传输时未遭截断。
    3. 确认在边界处提供的密钥正是文档加密时所用的密钥。
    4. 重新执行该调用。
  • 相关。 签名与时间戳失败
  • 症状。 抛出 NextPDF\Security\Exception\TamperedDataException,而非 DecryptionFailedException
  • 可能原因。 完整性检查已执行且未通过。这有别于结构性解密失败:当时有足够的素材可评估完整性,但完整性验证未通过。
  • 证据/诊断。 对照源码中的这两个类:DecryptionFailedException 属于结构性问题,并非安全事件;TamperedDataException 则表示内容经过验证后未通过。
  • 解法。
    1. 将输入视为不可信;不要使用解密后的内容。
    2. 从可信来源重新获取该文档。
    3. 若改用已知良好的来源后失败仍然持续,请捕获 getContext() 以供事件报告之用。
  • 相关。 签名与时间戳失败
  • 症状。 生成的文档已设定权限标志(例如禁止复制或打印),但阅读器仍然复制或打印了内容。
  • 可能原因。 这是预期内的边界,而非缺陷。本库不会将传入核心加密字典构建器的权限整数作为强制手段应用。这些标志属于建议性元数据;不遵守它们的阅读器并不会被 NextPDF 阻挡。
  • 证据/诊断。 src/Security/Encryption/EncryptionDictionaryBuilder.php 声明了 buildDict(int $permissions, string $fileId),其中参数记载为 ignored; retained for forward compatibility。该方法开头即执行 unset($permissions, $fileId)。由 src/Inspect/PdfPermissions.php 暴露的权限标志是只读的检查字段,而非强制执行层。
  • 解法。
    1. 不要依赖权限标志来阻止打印、复制或修改。 生成器库无法强制执行这些标志。
    2. 在必须限制访问的场景下,请管控文件本身的分发,或在 PDF 之外应用访问控制系统。
    3. 只将 PdfPermissions 用于报告既有文档所声明的标志,而非用来断言那些动作已被阻止。
  • 相关。 签名与时间戳失败
  • 症状。 当同一次构建同时启用 PDF/A 并请求加密时,抛出 NextPDF\Security\Exception\IncompatiblePdfAModeException
  • 可能原因。 PDF/A 配置文件禁止在尾部(trailer)中使用 Encrypt 键。无论调用顺序如何,引擎都会拒绝这个组合。
  • 证据/诊断。 请参阅 PDF/A 与 PDF/UA 条目 中引用的条款、getContext() 字段,以及失败路径测试。
  • 解法。
    1. 决定这份文档需要的是归档一致性,还是加密。
    2. 移除你不需要的那项属性对应的调用。
    3. 重新执行该管线。
  • 相关。 PDF/A 与 PDF/UA 验证
  • DecryptionFailedExceptionTamperedDataException 代表不同含义:分别是结构性失败与完整性验证失败。请按类进行分支判断,而非按消息文本。
  • 核心加密字典构建器会忽略权限整数;如果某个构建依赖核心包提供权限强制执行,那就是基于误解。
  • PdfPermissions 只在完整检查深度下,针对已加密文档才会被填充,且反映其声明的标志。字段有值并不代表该动作已被阻止。

术语表:权限标志 · 已验证解密