Un indicador de permisos de PDF no es un cerrojo. Es una petición que el archivo le hace a lo que sea que lo abra, y un visor es libre de ignorarla. Ese único hecho decide cómo debe razonar sobre todas las demás decisiones de esta página. La confidencialidad real viene de un solo sitio: el cifrado AES-256 con una clave derivada de una contraseña que el lector no tiene. Todo lo demás, las casillas de "no imprimir" y "no copiar", es política que el software conforme acepta respetar y el software hostil no. Confunda esas dos capas y entregará algo que parece seguro en una demo y tiene fugas en producción
HotPDF es un componente PDF VCL nativo para Delphi y C++Builder, y expone el modelo de protección de ISO 32000 mediante un pequeño conjunto de propiedades. Las propiedades son fáciles de establecer. Lo difícil es saber cuál le compra protección criptográfica y cuál le compra una sugerencia educada, y acertar con el orden de asignación para que el cifrado que pidió sea de verdad el cifrado que obtiene
Lo que prometen realmente las dos contraseñas
El cifrado PDF define dos credenciales con cometidos distintos, y confundirlas es el error de diseño más común en el código de salida protegida. La contraseña de usuario controla el descifrado. Sin ella, o sin la contraseña de propietario, un lector conforme no puede reconstruir la clave del archivo y el contenido permanece criptográficamente ilegible. La contraseña de propietario controla en cambio la configuración de permisos: un lector que recibe la contraseña de propietario obtiene acceso completo digan lo que digan los indicadores de restricción
Los bits de permisos se apoyan en terreno más débil. Impresión, extracción de contenido, relleno de formularios: cada uno es un indicador que el visor lee y decide respetar (ISO 32000-2 §7.6.4). El cifrado protege los bytes. Los indicadores de permisos solo dan instrucciones al software conforme, y se las dan a posteriori. Quien abre el documento con la contraseña de usuario ya tiene el contenido descifrado en memoria, así que "no copiar" y "no imprimir" significan algo para un visor bien educado y nada para uno decidido. Construya el modelo de amenazas en torno a esa línea. La confidencialidad vive en la contraseña de usuario. Los permisos moldean lo que ofrecen los visores habituales, y eso es todo lo que hacen
Orden de configuración: todo antes de BeginDoc
HotPDF construye el diccionario de cifrado y deriva la clave del archivo en el momento en que se ejecuta BeginDoc. Lo que contengan las propiedades de protección en ese instante es lo que recibe el documento, y cambiarlas después no cambia nada. La propiedad que más importa aquí es CryptKeyLength, que elige el esquema entre los valores k40, k128, aes128 y aes256 de THPDFKeyType. Asígnela después de BeginDoc y no obtendrá ninguna excepción ni advertencia, solo un archivo que conservó en silencio lo que tenía al empezar. Esa clase de divergencia silenciosa es la peor: pasa todas las pruebas locales y aparece meses después como un hallazgo de cumplimiento en la mesa de un cliente
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'statement.pdf';
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256; // debe establecerse antes de BeginDoc
Pdf.UserPassword := 'open-secret';
Pdf.OwnerPassword := 'admin-secret';
Pdf.UseAES256R6 := False; // R=5: máxima compatibilidad con visores
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 720, 0, 'Account statement, June 2026');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Las contraseñas son UTF-8 y tienen un tope de 127 bytes, que es el límite de ISO 32000-2 para los esquemas AES-256. Si su política de contraseñas le entrega secretos más largos, haga usted mismo el truncado, en su lado, donde controla exactamente dónde cae el corte. Déjelo al azar y la biblioteca y algún visor futuro pueden discrepar sobre el punto de corte, lo que produce un archivo que se abre para usted y rechaza la misma contraseña en otro sitio
Revisión 5 o revisión 6: un booleano, dos ecosistemas
UseAES256R6 elige entre los dos protocolos AES-256, y la elección tiene más consecuencias de lo que sugiere su tipo booleano. Déjelo en False y HotPDF escribe la revisión 5, el esquema AES-256 que llegó como extensión de PDF 1.7 y que pueden abrir algo así como quince años de visores. Póngalo en True y obtiene la revisión 6, la derivación de clave endurecida que ISO 32000-2 estandarizó para PDF 2.0 y que cierra una debilidad conocida en cómo la revisión 5 verifica la contraseña
Así que la revisión 6 es criptográficamente la mejor historia. También es la que rompe cosas. Un archivo de revisión 6 necesita un visor construido para PDF 1.7 Extension Level 3 o PDF 2.0, y mucho software desplegado no es ni lo uno ni lo otro: archivos de gestión documental, renderizadores incrustados en otros productos, herramientas de negocio que nadie ha tocado en años. Esos rechazarán el archivo de plano, y lo harán en la máquina del cliente, nunca en la suya. El valor por defecto práctico es por tanto la revisión 5. Recurra a la revisión 6 solo cuando una política de seguridad nombre ISO 32000-2 por revisión, y cuando haya confirmado de verdad que todos los consumidores pueden leerla. En cualquier caso, deje por escrito cuál eligió y por qué, porque la siguiente persona que toque este código se lo preguntará
Los tipos de clave más antiguos merecen una frase para que sepa saltárselos. THPDFKeyType sigue listando k40, k128 y aes128, pero existen para reproducir archivos históricos, no para proteger otros nuevos. RC4 de 40 bits cae ante hardware corriente, y los esquemas de 128 bits son anteriores a las revisiones AES-256 que cualquier revisión de seguridad actual esperará. Para un documento que está creando en 2026 la única pregunta real es revisión 5 frente a revisión 6; si se sorprende recurriendo a los tipos heredados en un diseño nuevo, algo ha ido mal más arriba
Indicadores de permisos sin contraseña de apertura
A menudo el requisito es lo contrario del secreto. Cualquiera debería poder leer el documento, pero se pretende limitar la impresión o la extracción. Eso se expresa con una contraseña de usuario vacía y una contraseña de propietario no vacía, lo que PDF llama modo de contraseña de apertura, y se enumeran las operaciones que se quieren permitir en ProtectOptions
Pdf.ActivateProtection := True;
Pdf.CryptKeyLength := aes256;
Pdf.UserPassword := ''; // cualquiera puede abrir el archivo
Pdf.OwnerPassword := 'rotate-me-quarterly'; // protege el conjunto de permisos
Pdf.ProtectOptions := [prPrint, prPrint12bit, prExtractContent];
Pdf.BeginDoc;
// ... contenido de la página ...
Pdf.EndDoc;
El conjunto THPDFProtectOptions se corresponde con los bits de permisos ISO: prPrint y prPrint12bit para impresión de alta resolución, prInformationCopy para copia y extracción en general, prExtractContent para la extracción por tecnologías de asistencia, además de prModifyStructure, prEditAnnotations, prFillAnnotations y prAssemble. Dos de ellos merecen una advertencia. Deje prExtractContent activado en casi todos los perfiles que construya. Es el bit que un lector de pantalla necesita para llegar al texto, y desactivarlo convierte en silencio una decisión sobre derechos en un defecto de accesibilidad que sufre alguien con discapacidad y que usted nunca ve. La otra trampa es prPrint a solas, sin prPrint12bit: varios visores responden degradando la calidad de impresión, y sus usuarios lo reportarán como un fallo de renderizado en lugar del ajuste de permisos que realmente es
La verificación lleva cinco minutos y pertenece a su lista de comprobación de lanzamiento. Abra una muestra de cada perfil en Acrobat, abra Propiedades del documento y lea la pestaña Seguridad, que detalla el algoritmo ("AES de 256 bits") y enumera las operaciones permitidas una por una. Después abra el mismo archivo en el visor más antiguo que realmente usen sus clientes, no en el más nuevo de su máquina. Esa segunda apertura es el seguro barato contra un archivo de revisión 6 que pasa el desarrollo sin problemas y muere en un cliente que nunca actualizó
Quitar la protección de archivos existentes
El descifrado recorre el mismo modelo de propiedades al revés. Cargue el documento con una credencial válida, desactive la protección y guarde el resultado sin ella
var
Pdf: THotPDF;
PageCount: Integer;
begin
Pdf := THotPDF.Create(nil);
try
PageCount := Pdf.LoadFromFile('encrypted.pdf', 'open-secret');
if PageCount > 0 then
begin
Pdf.ActivateProtection := False; // elimina el cifrado al guardar
Pdf.SaveLoadedDocument('plain.pdf');
end;
finally
Pdf.Free;
end;
end;
Esa ruta analiza el documento completo en memoria, lo que está bien para archivos corrientes y es un derroche para los enormes. Cuando la entrada alcanza cientos de megabytes, DecryptFile es la opción más barata: descifra durante una copia a nivel de archivo, tomando una ruta de reescritura AES-256 directa que evita construir el árbol de objetos completo siempre que la entrada lo permite. Forma parte de la Direct File API tratada en el artículo complementario sobre procesar PDF grandes desde Delphi
Restricciones que interactúan con el cifrado
Hay dos límites que conviene conocer antes de diseñar en torno al cifrado y no después. El primero es la conformidad de archivado. ISO 19005 prohíbe el cifrado en PDF/A, así que cualquier flujo de trabajo que cifre un documento y a la vez reclame conformidad PDF/A es contradictorio por construcción; HotPDF no le permitirá tener ambas cosas en un mismo archivo. Cuando de verdad necesite las dos, la respuesta son dos artefactos: una copia cifrada para distribución y una copia sin cifrar aparte para el archivo
El segundo límite es más crudo. El cifrado PDF no tiene custodia de claves ni recuperación. Pierda la contraseña de usuario de un archivo R5 o R6 y sus opciones son la fuerza bruta o rendirse. Así que trate los secretos de propietario y de usuario como trata cualquier credencial de producción. Genérelos, guárdelos en un almacén de secretos, rótelos según un calendario. Lo único que nunca hay que hacer es codificarlos como constantes en una unidad, donde viajan directos al control de versiones y se quedan para siempre en la copia de trabajo de cada desarrollador
Un último reflejo que merece la pena cultivar. Cambiar la protección de un archivo que usted no creó es la misma maquinaria que el descifrado, no una función aparte: cárguelo con su contraseña mediante LoadFromFile, edite ProtectOptions o las contraseñas en el sitio y vuelva a escribirlo con SaveLoadedDocument. Si puede descifrar un archivo, puede cambiarle los permisos, y el código es casi idéntico al ejemplo anterior
Las propiedades de protección mostradas aquí forman parte del HotPDF Delphi Component estándar para Delphi y C++Builder; la página del producto incluye la referencia completa de cifrado, incluida la enumeración completa de permisos