Ir al contenido

Solución de problemas: cifrado y banderas de permisos

Estas entradas cubren los fallos de descifrado que el motor notifica mediante NextPDF\Exception\EncryptionException y NextPDF\Security\Exception\DecryptionFailedException, así como el límite de las banderas de permisos del PDF.

Primero, una aclaración sobre el límite, porque evita el malentendido más común: las banderas de permisos del PDF en el diccionario de cifrado registran la intención del autor. No son un mecanismo de control de acceso que esta biblioteca haga cumplir. Un lector que ignore las banderas todavía puede imprimir, copiar o modificar el contenido. Conviene tratarlas como una petición dirigida a un lector cooperativo, no como una imposición.

  • Síntoma. EncryptionException con un mensaje de la forma Encryption operation "<op>" failed using algorithm "<algorithm>".
  • Causa probable. La operación de cifrado no pudo ejecutarse, normalmente por una extensión OpenSSL ausente o mal configurada, material de clave no válido, o un tamaño de IV no válido en el límite del cifrador.
  • Evidencia / diagnóstico. getContext() devuelve algorithm y operation. El valor de operation es uno de encrypt, decrypt o key_derivation, lo que indica qué etapa falló.
  • Solución.
    1. Confirmar que la extensión OpenSSL de PHP está instalada y cargada.
    2. Leer el campo operation para localizar la etapa que falla.
    3. Para key_derivation, verificar las entradas de contraseña o clave.
    4. Volver a ejecutar la llamada.
  • Relacionado. Referencia de excepciones.

Entrada: el descifrado falla por un motivo estructural

Sección titulada «Entrada: el descifrado falla por un motivo estructural»
  • Síntoma. DecryptionFailedException con un mensaje de la forma Decryption failed for "<algorithm>": <reason>.
  • Causa probable. El texto cifrado no se pudo procesar por un motivo no relacionado con manipulación, por ejemplo, un texto cifrado truncado, un IV ausente, o una clave incorrecta suministrada en el límite de la API. La comprobación de integridad no se ejecutó porque no había material suficiente para evaluarla.
  • Evidencia / diagnóstico. getContext() devuelve algorithm y reason. DecryptionFailedException se documenta en el código fuente como distinta de TamperedDataException: esta excepción representa un error de configuración o de transporte, no un indicio de manipulación. No debe tratarse por sí sola como un incidente de seguridad.
  • Solución.
    1. Leer reason para identificar el defecto estructural, por ejemplo ciphertext shorter than IV+tag.
    2. Verificar que el texto cifrado se transportó sin truncamiento.
    3. Confirmar que la clave suministrada en el límite es la clave con la que se cifró el documento.
    4. Volver a ejecutar la llamada.
  • Relacionado. Fallos de firma y de marca de tiempo.

Entrada: se lanza una excepción de «datos manipulados»

Sección titulada «Entrada: se lanza una excepción de «datos manipulados»»
  • Síntoma. NextPDF\Security\Exception\TamperedDataException en lugar de DecryptionFailedException.
  • Causa probable. La comprobación de integridad se ejecutó y no se superó. Esto es distinto de un fallo estructural de descifrado: había material suficiente para evaluar la integridad, pero no se mantuvo.
  • Evidencia / diagnóstico. El código fuente contrasta las dos clases: DecryptionFailedException es estructural y no es un incidente de seguridad; TamperedDataException indica que el contenido autenticado no se verificó.
  • Solución.
    1. Tratar la entrada como no confiable; no consumir el contenido descifrado.
    2. Volver a obtener el documento desde una fuente confiable.
    3. Si el fallo persiste con una fuente conocida como buena, capturar getContext() para un informe de incidente.
  • Relacionado. Fallos de firma y de marca de tiempo.

Entrada: las banderas de permisos no detienen una acción posterior

Sección titulada «Entrada: las banderas de permisos no detienen una acción posterior»
  • Síntoma. Se generó un documento con banderas de permisos establecidas, por ejemplo, copia o impresión no permitidas, y aun así un lector copia o imprime el contenido.
  • Causa probable. Este es el límite esperado, no un defecto. Esta biblioteca no impone el entero de permisos que se pasa al constructor del diccionario de cifrado del núcleo. Las banderas son metadatos consultivos; NextPDF no bloquea a un lector que no las respete.
  • Evidencia / diagnóstico. src/Security/Encryption/EncryptionDictionaryBuilder.php declara buildDict(int $permissions, string $fileId) con el parámetro documentado como ignored; retained for forward compatibility. El método comienza con unset($permissions, $fileId). Las banderas de permisos que expone src/Inspect/PdfPermissions.php son campos de inspección de solo lectura, no una capa de imposición.
  • Solución.
    1. No depender de las banderas de permisos para detener la impresión, la copia o la modificación. Una biblioteca productora no puede imponerlas.
    2. Cuando el acceso deba restringirse, controlar la distribución del propio archivo, o aplicar un sistema de control de acceso fuera del PDF.
    3. Usar PdfPermissions solo para informar de las banderas que declara un documento existente, no para afirmar que esas acciones se impiden.
  • Relacionado. Fallos de firma y de marca de tiempo.
  • Síntoma. NextPDF\Security\Exception\IncompatiblePdfAModeException cuando una compilación habilita PDF/A y a la vez solicita cifrado.
  • Causa probable. El perfil PDF/A prohíbe la clave Encrypt en el tráiler. El motor rechaza la combinación en cualquier orden de llamada.
  • Evidencia / diagnóstico. Consulta la entrada de PDF/A y PDF/UA para la cláusula citada, los campos de getContext() y la prueba de la ruta de fallo.
  • Solución.
    1. Decidir si el documento necesita conformidad de archivado o cifrado.
    2. Eliminar la llamada de la propiedad que no se necesite.
    3. Volver a ejecutar la canalización.
  • Relacionado. Validación de PDF/A y PDF/UA.
  • DecryptionFailedException y TamperedDataException significan cosas distintas: fallo estructural frente a integridad fallida. Ramificar según la clase, no según el mensaje.
  • El constructor del diccionario de cifrado del núcleo ignora el entero de permisos; una compilación que dependa de que el paquete del núcleo imponga permisos se basa en un malentendido.
  • PdfPermissions se rellena solo para documentos cifrados en la profundidad de inspección completa, y refleja las banderas declaradas. Un campo rellenado no significa que la acción se impida.

Glosario: banderas de permisos · descifrado autenticado