Trabalhos de assinatura PFX incremental
A operação de assinatura suporta um perfil incremental validado que preserva a revisão PDF original exata e cada assinatura criptográfica existente, devolvendo um artefacto assinado separadamente
Selecionar um 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}}
O perfil por defeito pfx-unsigned-document mantém o comportamento original e aceita fontes sem quaisquer campos de assinatura; cria um campo novo usando page, x1, y1, x2 e y2 e restaura o grafo da fonte antes da publicação
pfx-incremental-document seleciona o perfil novo; incremental: true é um seletor equivalente quando profile é omitido, e entra em conflito com um perfil explicitamente diferente
existingField: true preenche o campo de assinatura vazio nomeado sem acrescentar outro campo; caso contrário a operação cria um campo novo, e page e retângulo identificam o widget dele
O default de fieldName é Signature1 e aceita 1 a 1024 bytes UTF-8; existingField exige um perfil incremental, um campo de assinatura correspondente e um valor V ausente ou null
O bit 1 de Ff só de leitura e flags inteiras malformadas ou fora do intervalo são rejeitadas antes da preparação; dicionários SV e Lock herdados são resolvidos com nomes PDF semanticamente únicos e travessia delimitada de pais
Valores de seed e bloqueios de campos
digestMethod seleciona o digest CMS real SHA256, SHA384 ou SHA512; SHA256 é o default, enquanto cades: true seleciona ETSI.CAdES.detached e inclui o atributo signing-certificate-v2 que vincula o certificado real de assinatura
reason, location e contactName são strings JSON UTF-8 escritas como strings de texto Unicode PDF; seeds exigidas de reasons comparam os valores Unicode delas, incluindo o valor especial de um único ponto que exige um reason omitido
Restrições SV exigidas verificam o handler real, o SubFilter CMS, a versão de assinatura suportada, o digest, o reason, a permissão de certificação, o atestado legal e o modo LockDocument; um timestamp exigido usa o transport da aplicação e o workflow explícito de confiança descrito em timestamps de assinatura em Windows, evidência exigida de revogação assinada usa assinatura autenticada de CRLs e OCSP, e aparências nomeadas exigidas usam presets reais de aparências de assinaturas geradas
Propriedades SVCert exigidas validam o certificado folha real do PFX e a cadeia de emissores incluída, bytes permitidos de certificados, OIDs de políticas de certificados, bits de key usage e atributos de DN de sujeitos Unicode antes de assinar
credentialSourceURL fornece proveniência de credenciais afirmada pela aplicação para um URL SVCert exigido; a biblioteca compara o URL declarado e o URLType suportado sem abrir esse endpoint nem autenticar uma identidade de transport
Bloqueios de campos All, Include e Exclude são escritos como um dicionário indireto SigFieldLock e uma referência FieldMDP correspondente vinculada ao Catalog do documento; os nomes de campos usam strings de texto Unicode PDF e permanecem encriptados em documentos encriptados
Um valor Lock P assinado limita revisões posteriores usando a política original assinada de campos, independentemente de qualquer permissão DocMDP; segundas assinaturas permitidas preservam a revisão e o CMS anteriores exatos, enquanto um campo bloqueado ou uma alteração P1 é rejeitada antes da publicação
A consulta de políticas descodifica escapes de PDF names exatamente uma vez, incluindo nomes Parent herdados; dicionários com nomes semânticos duplicados e pais inválidos ou cíclicos são rejeitados antes da publicação, enquanto nomes com escape válidos mantêm os bytes da fonte deles
contentsBytes tem por defeito 16384 e aceita 1024 a 1048576; reason, location e contactName preenchem o novo dicionário de assinaturas
Certificação e atestados legais
certificationPermission tem por defeito 0 para assinatura de aprovação; 1, 2 ou 3 cria uma assinatura de certificação com a permissão DocMDP pedida, vincula Catalog Perms DocMDP ao dicionário indireto real de assinaturas e mantém qualquer transform FieldMDP independente
A certificação tem de ser a primeira assinatura, e um documento pode conter apenas uma assinatura de certificação; permissões de Catalog malformadas, referências não resolvidas e valores DocMDP sem um binding original de campo assinado são rejeitados
legalAttestation é uma string Unicode opcional para assinatura de certificação e é escrita em Catalog Legal Attestation; uma lista exigida de LegalAttestation SV tem de conter o texto selecionado, enquanto uma lista exigida vazia exige omissão
Assinaturas de certificação P2 e P3 existentes permitem assinatura posterior de aprovação quando os bloqueios de campos e a política de revisões o permitirem; assinaturas P1 e campos bloqueados rejeitam alterações antes da publicação binária
Contrato de fontes
O perfil de trabalhos incrementais aceita uma fonte original retida, incluindo PDFs encriptados suportados, e um grafo de objetos carregado não modificado; forneça password na operação de assinatura para uma fonte encriptada, separadamente de pfxPassword
A palavra-passe da fonte autentica um snapshot bruto independente, inicializa o contexto original de encriptação e reabre o candidato assinado; a revisão incremental resultante preserva o prefixo de ciphertext original, o dicionário de segurança e o ID permanente do documento
A desencriptação pode marcar internamente objetos como dirty ou remover um dicionário de segurança do grafo descodificado; a operação compara esses estados e serializações delimitadas de objetos contra uma baseline de fonte recém-autenticada, rejeitando alterações reais do grafo e todos os estados de objetos descarregados
Para uma palavra-passe de utilizador, um campo de assinatura existente exige permissão de preenchimento de formulários ou de anotações, e um widget novo de assinatura exige permissão de anotações; uma palavra-passe de proprietário autenticada autoriza qualquer uma das operações, sujeita às políticas existentes de assinaturas
SaveLoadedDocumentToStream pode alterar o estado de serialização; ao assinar um grafo guardado ou editado, recarregue os bytes guardados num handle novo e assine essa revisão
Mantenha o armazenamento da fonte original estável durante o tempo de vida do handle; os trabalhos de ficheiros negam partilha de escrita enquanto carregam e preparam o snapshot deles
O handle original mantém as contagens de campos dele, a identidade existente de campos, os valores de formulários, os bytes da fonte e as definições anteriores de lançamento e de descodificação; todo o sucesso de assinatura devolve documentUpdated: false, e falhas de assinatura deixam o handle disponível para consulta, gravação ou um pedido válido posterior
Trabalhos de ficheiros rejeitam um caminho de saída que iguale ou seja alias do ficheiro de entrada, incluindo hard links; APIs diretas de streams rejeitam aliases reconhecíveis de streams de fonte e de ficheiros fonte, e quem chama também tem de manter o armazenamento de saída de callbacks opacos distinto do armazenamento de entrada
Preparação e validação
A operação copia bytes brutos da fonte para um snapshot temporário criado exclusivamente, abre um clone incremental independente, acrescenta o placeholder através de SaveIncrementalUpdate delimitado e preenche o CMS destacado através do assinador nativo de streams PFX
O PFX permanece aberto com partilha de escrita negada desde o preflight de tamanho até à assinatura; ficheiros temporários usam CREATE_NEW e são removidos apenas quando a operação é dona da criação deles
O candidato assinado tem de conter o prefixo exato de bytes da fonte e as contagens esperadas de formulários e de campos de assinatura; a assinatura nova tem de verificar no campo selecionado dela, todas as assinaturas previamente preenchidas têm de continuar a verificar, e a análise de revisões de todas as assinaturas antigas tem de aceitar restrições de DocMDP, FieldMDP, usage-rights e identidade
Campos antigos não preenchidos são retidos sem serem contados como preservedSignatures; assinaturas existentes malformadas, inválidas ou violadoras de políticas causam rejeição antes da publicação binária
A verificação de assinaturas existentes verifica a integridade CMS contra bytes assinados e a política nativa de revisões; quando é pedido um timestamp para a assinatura nova, a resposta dele valida separadamente a confiança explícita de TSA e a evidência configurada de revogação antes da publicação
Orçamentos e publicação
O teto efetivo de saída é min(outputBytes, memoryBytes / 8) e inclui o prefixo completo da fonte, objetos acrescentados, xref e a reserva de assinaturas; effectiveOutputLimit reporta o teto aplicado
O candidato não assinado e a saída assinada são separadamente delimitados por esse teto, os bytes do PFX são limitados a memoryBytes / 8, e os orçamentos de descodificação de baseline de fonte, clone e candidato são separadamente limitados a memoryBytes / 8 com limiares de descarga para ficheiro não superiores a 1 MiB
Estes são orçamentos de operações e de buffers, e não uma garantia estrita de RSS do processo; criptografia, metadados de objetos, análise de revisões e a fonte já carregada de quem chama podem exigir memória residente adicional
Verificações de cancelamento e de tempo decorrido aplicam-se à cópia da fonte, à serialização e cópia de deltas, a leituras de candidatos, a leituras de verificação de assinaturas, a leituras de análise de revisões e à publicação por callbacks; falhas nativas persistentes de streams mantêm a categoria delas de orçamento ou de cancelamento na fronteira do trabalho
A saída binária é preparada e validada antes do primeiro callback de saída, e o tamanho do JSON de resultados é verificado antes da publicação binária; a saída de callbacks em si não é atómica, pelo que um callback binário ou de resultados falhado pode deixar bytes que quem chama tem de descartar
Trabalhos de ficheiros escrevem num candidato próprio no mesmo diretório, fazem flush dele, fecham handles de fonte e de saída e substituem atomicamente um alvo distinto após validação bem-sucedida; falhas preservam um destino existente
O sucesso devolve mediaType: application/pdf, fieldName, profile, incremental, existingField, certificationPermission, revocationInfo, appearanceProfile, preservedSignatures, effectiveOutputLimit, outputBytes e documentUpdated: false
Aceitação de replay
$env:HOTPDF_SUPPRESS_AUTO_LAUNCH = '1'
./Tests/CABI/Run-IncrementalSigningAcceptance.ps1 -BuildDLL -CheckFPC
O runner descobre o RAD Studio através do RootDir do registo dele, aceita overrides de RADStudioRoot e de PythonExecutable, e usa o toolchain FPC configurado quando CheckFPC está selecionado; FPCOnly reproduz apenas esses alvos nativos, enquanto OpenSSLWin32Library e OpenSSLWin64Library selecionam bibliotecas de runtime correspondentes para cada arquitetura
O runner não GUI verifica ambas as APIs nativas Win32 e Win64 e DLLs reais da ABI C usando callbacks parciais, campos vazios existentes, assinaturas anteriores, valores de seeds exigidos, CAdES real SHA384 e SHA512, metadados Unicode, segundas assinaturas permitidas e bloqueadas, propriedades reais de certificados PFX, transforms AES-128 e AES-256 de bloqueios de campos, restrições de permissões e credenciais de proprietário, palavras-passe incorretas, grafos descodificados dirty, snapshots exatos de fontes encriptadas, recuperação de escritores encriptados no local, fixtures reais de CMS DocMDP P1 e P2, orçamentos, cancelamento, falhas de callbacks e reutilização de fontes após falhas
Verificações independentes de pypdf, MuPDF e OpenSSL provam prefixos anteriores e intervalos de bytes exatos, encriptação e IDs permanentes inalterados, texto original pesquisável, valores CMS antigos e novos válidos, a exceção de encriptação do Contents de assinaturas e a rejeição de conteúdo assinado alterado; independent-proof.json regista os intervalos de bytes e os resultados das provas
Tópicos relacionados
Operações de documentos, CopyLoadedSourceToStream, SaveIncrementalUpdate, EHPDFIncrementalOutputBudget