Trabajos de firma incremental PFX
La operación sign soporta un perfil incremental validado que preserva la revisión PDF original exacta y cada firma criptográfica existente, mientras devuelve un artifact firmado por separado
Selección de perfil
{"schemaVersion":1,"type":"sign","profile":"pfx-incremental-document",
"pfxFile":"C:/keys/signer.pfx","pfxPassword":"password",
"fieldName":"ApprovalTwo","existingField":true,
"budget":{"memoryBytes":268435456,"outputBytes":134217728,
"resultBytes":16777216,"timeMilliseconds":60000,
"objectCount":1000000,"pageCount":1024}}
El perfil pfx-unsigned-document por defecto conserva el comportamiento original y acepta fuentes sin ningún campo de firma; crea un campo nuevo usando page, x1, y1, x2 e y2 y restaura el graph fuente antes de publicar
pfx-incremental-document selecciona el perfil nuevo; incremental: true es un selector equivalente cuando se omite profile, y entra en conflicto con un profile explícitamente distinto
existingField: true llena el campo de firma nombrado vacío sin agregar otro campo; de lo contrario la operación crea un campo nuevo, y page y el rectángulo identifican su widget
El default de fieldName es Signature1 y acepta de 1 a 1024 bytes UTF-8; existingField exige un perfil incremental, un campo de firma coincidente y un value V ausente o null
El bit read-only 1 de Ff y los flags enteros malformados o fuera de rango se rechazan antes de la preparación; los diccionarios SV y Lock heredados se resuelven con nombres PDF semánticos únicos y traversal acotado de padres
Seed values y locks de campos
digestMethod selecciona el digest CMS real SHA256, SHA384 o SHA512; SHA256 es el default, mientras que cades: true selecciona ETSI.CAdES.detached e incluye el atributo signing-certificate-v2 que vincula el certificado de firma real
reason, location y contactName son cadenas JSON UTF-8 escritas como cadenas de texto Unicode PDF; los seed reasons requeridos comparan sus valores Unicode, incluido el valor especial de punto único que exige omitir reason
Las restricciones SV requeridas comprueban el handler real, el SubFilter CMS, la versión de firma soportada, el digest, el reason, el permiso de certificación, el attestation legal y el modo LockDocument; un timestamp requerido usa el transporte de la aplicación y el workflow de trust explícito descrito en timestamps de firma en Windows, la evidencia de revocación firmada requerida usa firma autenticada de CRL y OCSP, y las apariencias nombradas requeridas usan presets reales de apariencia de firma generada
Las propiedades SVCert requeridas validan el certificado leaf real del PFX y la cadena de issuer incluida, los bytes de certificado permitidos, los OIDs de política de certificado, los bits de key usage y los atributos de subject DN Unicode antes de firmar
credentialSourceURL suministra provenance de credenciales declarado por la aplicación para una URL SVCert requerida; la biblioteca compara la URL declarada y el URLType soportado sin abrir ese endpoint ni autenticar una identidad de transporte
Los locks de campos All, Include y Exclude se escriben como un diccionario indirecto SigFieldLock y una referencia FieldMDP coincidente vinculada al Catalog del documento; los nombres de campos usan cadenas de texto Unicode PDF y permanecen cifrados en documentos cifrados
Un valor P de Lock firmado limita las revisiones posteriores usando la política original del campo firmado, independientemente de cualquier permiso DocMDP; las segundas firmas permitidas preservan la revisión previa exacta y el CMS, mientras que un campo bloqueado o un cambio P1 se rechaza antes de publicar
El lookup de políticas decodifica los escapes de nombres PDF exactamente una vez, incluidos los nombres Parent heredados; los diccionarios con nombres semánticos duplicados y los padres inválidos o cíclicos se rechazan antes de publicar, mientras que los nombres escapados válidos retienen sus bytes fuente
contentsBytes vale 16384 por defecto y acepta de 1024 a 1048576; reason, location y contactName llenan el nuevo diccionario de firma
Certificación y attestations legales
certificationPermission vale 0 por defecto para la firma de aprobación; 1, 2 o 3 crea una firma de certificación con el permiso DocMDP solicitado, vincula Catalog Perms DocMDP al diccionario de firma indirecto real y retiene cualquier transform FieldMDP independiente
La certificación debe ser la primera firma, y un documento puede contener solo una firma de certificación; los permisos de Catalog malformados, las referencias no resueltas y los valores DocMDP sin binding a un campo firmado original se rechazan
legalAttestation es una cadena Unicode opcional para la firma de certificación y se escribe en Catalog Legal Attestation; una lista LegalAttestation de SV requerida debe contener el texto seleccionado, mientras que una lista requerida vacía exige omitirlo
Las firmas de certificación P2 y P3 existentes permiten firmas de aprobación posteriores cuando los locks de campos y la política de revisión lo permiten; las firmas P1 y los campos bloqueados rechazan cambios antes de la publicación binaria
Contrato de la fuente
El perfil incremental de jobs acepta una fuente original retenida, incluidos PDFs cifrados soportados, y un object graph cargado sin modificar; provee password en la operación sign para una fuente cifrada, separado de pfxPassword
El password de la fuente autentica un snapshot raw independiente, inicializa el contexto de cifrado original y reabre el candidato firmado; la revisión incremental resultante preserva el prefijo de ciphertext original, el security dictionary y el document ID permanente
El descifrado puede marcar internamente objetos como dirty o eliminar un security dictionary del graph descifrado; la operación compara estos estados y las serializaciones acotadas de objetos contra un baseline de fuente recién autenticado, mientras rechaza cambios reales del graph y todos los estados de objetos con flush
Con un user password, un campo de firma existente exige permiso de form-fill o de anotaciones, y un widget de firma nuevo exige permiso de anotaciones; un owner password autenticado autoriza cualquiera de las dos operaciones, sujeto a las políticas de firmas existentes
SaveLoadedDocumentToStream puede cambiar el estado de serialización; al firmar un graph guardado o editado, recarga los bytes guardados en un handle nuevo y firma esa revisión
Mantén el almacenamiento de la fuente original estable durante la vida del handle; los file jobs deniegan el write sharing mientras cargan y preparan su snapshot
El handle original retiene sus conteos de campos, la identidad de campos existentes, los valores de formulario, los bytes fuente y los ajustes previos de launch y decode; cada firma exitosa devuelve documentUpdated: false, y los fallos de firma dejan el handle disponible para consultar, guardar o una petición válida posterior
Los file jobs rechazan un path de salida que iguale o sea alias del archivo de entrada, incluidos los hard links; las APIs directas de stream rechazan alias reconocibles de source-stream y source-file, y los callers también deben mantener el almacenamiento opaco de salida de callbacks distinto del almacenamiento de entrada
Preparación y validación
La operación copia los bytes raw de la fuente a un snapshot temporal creado en exclusiva, abre un clon incremental independiente, agrega el placeholder mediante SaveIncrementalUpdate acotado y llena el CMS detached mediante el firmador nativo de streams PFX
El PFX permanece abierto con write sharing denegado desde el preflight de tamaño hasta la firma; los archivos temporales usan CREATE_NEW y solo se eliminan cuando la operación creó los suyos
El candidato firmado debe contener el prefijo de bytes fuente exacto y los conteos esperados de campos de formulario y firma; la firma nueva debe verificar en su campo seleccionado, cada firma previamente poblada debe seguir verificando, y el análisis de revisión de cada firma antigua debe aceptar las restricciones DocMDP, FieldMDP, usage-rights e identidad
Los campos antiguos sin poblar se retienen sin contarse como preservedSignatures; las firmas existentes malformadas, inválidas o que violen la política causan rechazo antes de la publicación binaria
La verificación de firmas existentes comprueba la integridad CMS contra los bytes firmados y la política nativa de revisión; cuando se solicita timestamp para la firma nueva, su respuesta valida por separado el trust explícito del TSA y la evidencia de revocación configurada antes de publicar
Presupuestos y publicación
El tope efectivo de salida es min(outputBytes, memoryBytes / 8) e incluye el prefijo fuente completo, los objetos agregados, el xref y la reserva de firma; effectiveOutputLimit reporta el tope aplicado
El candidato sin firmar y la salida firmada quedan acotados por separado por ese tope, los bytes del PFX se acotan a memoryBytes / 8, y los presupuestos de decode de baseline de fuente, clon y candidato se acotan por separado a memoryBytes / 8 con thresholds de spilling a archivo de 1 MiB como máximo
Estos son presupuestos de operación y buffers más que una garantía estricta de RSS del proceso; la criptografía, los metadatos de objetos, el análisis de revisiones y la fuente ya cargada del caller pueden exigir memoria residente adicional
Las comprobaciones de cancelación y tiempo transcurrido aplican a la copia de la fuente, la serialización y copia del delta, las lecturas del candidato, las lecturas de verificación de firmas, las lecturas de análisis de revisiones y la publicación por callback; los fallos nativos sticky de streams retienen su categoría de presupuesto o cancelación en el límite del job
La salida binaria se prepara en staging y se valida antes del primer callback de salida, y el tamaño del JSON de resultado se comprueba antes de la publicación binaria; la salida por callback no es atómica, así que un callback binario o de resultado fallido puede dejar bytes que el caller debe descartar
Los file jobs escriben a un candidato propio en el mismo directorio, le hacen flush, cierran los handles de fuente y salida y reemplazan atómicamente un destino distinto tras la validación exitosa; los fallos preservan un destino existente
El éxito devuelve mediaType: application/pdf, fieldName, profile, incremental, existingField, certificationPermission, revocationInfo, appearanceProfile, preservedSignatures, effectiveOutputLimit, outputBytes y documentUpdated: false
Aceptación por replay
$env:HOTPDF_SUPPRESS_AUTO_LAUNCH = '1'
./Tests/CABI/Run-IncrementalSigningAcceptance.ps1 -BuildDLL -CheckFPC
El runner descubre RAD Studio mediante su RootDir del registro, acepta overrides RADStudioRoot y PythonExecutable, y usa el toolchain FPC configurado cuando se selecciona CheckFPC; FPCOnly reproduce solo esos targets nativos, mientras que OpenSSLWin32Library y OpenSSLWin64Library seleccionan las bibliotecas de runtime coincidentes para cada arquitectura
El runner sin GUI comprueba las APIs nativas Win32 y Win64 y las DLLs reales de la C ABI usando callbacks parciales, campos vacíos existentes, firmas previas, seed values requeridos, CAdES real SHA384 y SHA512, metadatos Unicode, segundas firmas permitidas y bloqueadas, propiedades reales de certificados PFX, transforms de locks de campos AES-128 y AES-256, restricciones de permisos y credenciales owner, passwords incorrectos, graphs descifrados dirty, snapshots exactos de fuentes cifradas, recuperación del writer in-place cifrado, fixtures CMS reales DocMDP P1 y P2, presupuestos, cancelación, fallos de callbacks y reutilización de la fuente tras fallos
Las comprobaciones independientes de pypdf, MuPDF y OpenSSL prueban los prefijos previos y byte ranges exactos, el cifrado y los IDs permanentes sin cambios, el texto original buscable, los valores CMS válidos antiguos y nuevos, la excepción de cifrado del Contents de la firma y el rechazo de contenido firmado modificado; independent-proof.json registra los byte ranges y los resultados de las pruebas
Temas relacionados
Operaciones de documento, CopyLoadedSourceToStream, SaveIncrementalUpdate, EHPDFIncrementalOutputBudget