Pular para o conteúdo

Solução de problemas: falhas de assinatura e carimbo de tempo

Estas entradas cobrem falhas de assinatura geradas por NextPDF\Exception\SignatureException e NextPDF\Security\Signature\Exception\SignatureLevelUnreachableException. Cada entrada indica o método de fábrica ou a classe exata, para que você possa confirmar a causa pela mensagem e por getContext(), em vez de inferi-la.

Observação sobre a redação: o engine não certifica que uma assinatura seja válida nem que um documento esteja protegido. Ele relata a falha que detectou. Trate cada resolução como uma etapa para eliminar uma causa relatada.

Entrada: o nível PAdES “B-LT” ou “B-LTA” não pode ser produzido

Seção intitulada “Entrada: o nível PAdES “B-LT” ou “B-LTA” não pode ser produzido”
  • Sintoma. SignatureException com o final de mensagem nextpdf/enterprise package is required for B-LT/B-LTA signatures.
  • Causa provável. O provedor de recursos para validação de longo prazo está ausente. B-LT e B-LTA incorporam material de revogação e um carimbo de tempo de arquivamento, e esse provedor é distribuído em nextpdf/enterprise.
  • Evidência / diagnóstico. A fábrica SignatureException::ltvCapabilityMissing() gera exatamente esta mensagem. getContext() retorna signature_level definido como o nível que você tentou.
  • Resolução.
    1. Instale o provedor executando composer require nextpdf/enterprise.
    2. Execute a chamada de assinatura novamente.
    3. Se você não puder instalar o provedor, solicite B-B ou B-T, que o pacote core pode produzir.
  • Relacionado. Referência de exceções.

Entrada: o nível de assinatura é inalcançável e a chamada é rejeitada

Seção intitulada “Entrada: o nível de assinatura é inalcançável e a chamada é rejeitada”
  • Sintoma. SignatureLevelUnreachableException com uma mensagem no formato PAdES level "<x>" is unreachable (highest achievable: "<y>").
  • Causa provável. O nível de conformidade solicitado depende de uma infraestrutura que não está disponível no momento da assinatura, normalmente uma autoridade de carimbo de tempo para B-T e superiores. O engine falha de forma fechada: ele não rebaixa silenciosamente para depois anunciar o nível superior.
  • Evidência / diagnóstico. getContext() retorna requestedLevel, highestAchievableLevel e reason. O campo reason identifica a lacuna de infraestrutura. Esse é o padrão de falha fechada introduzido para evitar um documento que declare um nível que ele não atende.
  • Resolução.
    1. Consulte o campo reason para identificar a infraestrutura ausente.
    2. Forneça o componente ausente. Por exemplo, configure uma autoridade de carimbo de tempo e execute a chamada novamente.
    3. Para aceitar intencionalmente um nível inferior, passe allowDegradation: true para PadesOrchestrator. Nesse caso, a chamada produz highestAchievableLevel e relata o nível que produziu.
  • Relacionado. Criptografia e permissões.

Entrada: o cliente da autoridade de carimbo de tempo é necessário, mas está ausente

Seção intitulada “Entrada: o cliente da autoridade de carimbo de tempo é necessário, mas está ausente”
  • Sintoma. SignatureException com o final TSA client is required for level <x> but none was provided.
  • Causa provável. Uma solicitação B-T, B-LT ou B-LTA precisa de um cliente de autoridade de carimbo de tempo, e o orquestrador não recebeu nenhum.
  • Evidência / diagnóstico. A fábrica SignatureException::tsaRequired() gera esta mensagem; getContext() traz o signature_level tentado.
  • Resolução.
    1. Configure um cliente de autoridade de carimbo de tempo e passe-o para o orquestrador.
    2. Execute a chamada novamente.
    3. Para produzir um nível que não precisa de carimbo de tempo, solicite B-B.
  • Relacionado. Referência de exceções.

Entrada: a URL do endpoint da autoridade de carimbo de tempo está vazia

Seção intitulada “Entrada: a URL do endpoint da autoridade de carimbo de tempo está vazia”
  • Sintoma. SignatureException com o final TSA endpoint URL is empty.
  • Causa provável. Um cliente de autoridade de carimbo de tempo foi criado com uma URL de endpoint vazia.
  • Evidência / diagnóstico. A fábrica SignatureException::tsaUrlEmpty() gera esta mensagem. Este é um defeito de configuração, não uma falha de rede.
  • Resolução.
    1. Defina uma URL de endpoint não vazia no cliente da autoridade de carimbo de tempo, como https://timestamp.example.com/tsa.
    2. Se o nível solicitado não exigir carimbo de tempo, remova a configuração do cliente da autoridade de carimbo de tempo.
    3. Execute a chamada novamente.
  • Relacionado. Referência de exceções.

Entrada: o espaço reservado da assinatura está ausente do buffer

Seção intitulada “Entrada: o espaço reservado da assinatura está ausente do buffer”
  • Sintoma. SignatureException com o final no /Contents <…> field found in PDF buffer (signature placeholder missing).
  • Causa provável. O estágio de assinatura recebeu um buffer sem contêiner de assinatura reservado; portanto, não há lugar para gravar a assinatura.
  • Evidência / diagnóstico. A fábrica SignatureException::signatureContentsNotFound() gera esta mensagem.
  • Resolução.
    1. Certifique-se de que o campo de assinatura e o respectivo espaço reservado sejam gravados antes da execução do estágio de assinatura.
    2. Execute o pipeline novamente para que o espaço reservado exista quando a assinatura começar.
  • Relacionado. Referência de exceções.

Entrada: o status de revogação é desconhecido (o respondedor OCSP recusou)

Seção intitulada “Entrada: o status de revogação é desconhecido (o respondedor OCSP recusou)”
  • Sintoma. SignatureException com o final OCSP responder returned non-successful OCSPResponseStatus "<status>".
  • Causa provável. O respondedor do Online Certificate Status Protocol (OCSP) não retornou um status successful, portanto não produziu nenhuma asserção de revogação. O engine segue o RFC 6960 §4.2.1, citado no código-fonte: um corpo de resposta preenchido é permitido apenas para o status successful (0). O engine se recusa a tratar uma resposta recusada como um resultado de confiança positivo.
  • Evidência / diagnóstico. A fábrica SignatureException::nonSuccessfulOcspResponseStatus() gera esta mensagem e informa o status relatado, como tryLater ou internalError. Um byte de status reservado ou desconhecido gera, em vez disso, SignatureException::reservedOcspResponseStatus().
  • Resolução.
    1. Identifique o status na mensagem. Para um status transitório, como tryLater, tente buscar a revogação novamente mais tarde.
    2. Para unauthorized ou malformedRequest, verifique a URL da solicitação OCSP e o certificado que o respondedor espera.
    3. Não suprima a falha para obter um artefato B-LT ou B-LTA; a asserção de revogação faz parte desse nível.
  • Relacionado. Referência de exceções.

Entrada: uma entrada da cadeia de certificados falha ao decodificar

Seção intitulada “Entrada: uma entrada da cadeia de certificados falha ao decodificar”
  • Sintoma. SignatureException com o final failed to base64-decode PEM body — input is not valid PEM.
  • Causa provável. Uma entrada da cadeia de certificados não está em um formato Privacy-Enhanced Mail (PEM) válido, normalmente por truncamento, um caractere fora do lugar ou um blob binário em Distinguished Encoding Rules (DER) fornecido onde se esperava PEM.
  • Evidência / diagnóstico. A fábrica SignatureException::pemDecodingFailed() gera esta mensagem durante a montagem da cadeia.
  • Resolução.
    1. Inspecione cada certificado da cadeia em busca de caracteres fora do lugar ou truncamento.
    2. Reexporte o certificado afetado no formato PEM.
    3. Execute a chamada de assinatura novamente.
  • Relacionado. Criptografia e permissões.

Entrada: o tipo de chave privada não corresponde ao algoritmo

Seção intitulada “Entrada: o tipo de chave privada não corresponde ao algoritmo”
  • Sintoma. SignatureException com o final expected private key of type "<x>" for the configured algorithm but got "<y>".
  • Causa provável. A chave privada carregada não corresponde ao algoritmo de assinatura configurado, como uma chave Rivest-Shamir-Adleman (RSA) combinada com uma seleção de Elliptic Curve Digital Signature Algorithm (ECDSA).
  • Evidência / diagnóstico. A fábrica SignatureException::unexpectedKeyType() gera esta mensagem e informa tanto a classe de chave esperada quanto a real.
  • Resolução.
    1. Verifique se o par de certificado e chave corresponde ao algoritmo que você selecionou.
    2. Altere a seleção do algoritmo para corresponder à chave ou carregue a chave que corresponde ao algoritmo.
    3. Execute a chamada de assinatura novamente.
  • Relacionado. Referência de exceções.

Entrada: o material de chave ou de assinatura Ed25519 está malformado

Seção intitulada “Entrada: o material de chave ou de assinatura Ed25519 está malformado”
  • Sintoma. SignatureException com um final que indica uma incompatibilidade de comprimento Ed25519 — por exemplo, Ed25519 signature length <n> ≠ expected 64 bytes, ou Ed25519 round-trip self-verify failed.
  • Causa provável. A build criptográfica em tempo de execução retornou material de chave ou de assinatura com o comprimento errado, ou uma assinatura recém-produzida falhou na verificação contra sua própria chave pública. O engine cita o RFC 8032 §3.4 no código-fonte, que fixa uma assinatura Ed25519 destacada em 64 bytes. O engine aborta em vez de emitir material que não consegue verificar por conta própria.
  • Evidência / diagnóstico. As fábricas relevantes são SignatureException::ed25519SignatureMalformed(), ::ed25519RoundTripVerifyFailed(), ::ed25519KeyParseFailed(), ::ed25519SeedInvalid(), ::ed25519SecretKeyMalformed() e ::ed25519PublicKeyInvalid(). Cada uma informa o comprimento observado.
  • Resolução.
    1. Reinstale a extensão libsodium do PHP; uma build sem componentes necessários ou corrompida é a causa documentada de material com comprimento errado.
    2. Confirme que a chave é uma chave Ed25519 e que o OpenSSL está na versão 1.1.1 ou mais recente.
    3. Execute a chamada de assinatura novamente.
  • Relacionado. Referência de exceções.

Entrada: o dicionário de carimbo de tempo de arquivamento não foi emitido

Seção intitulada “Entrada: o dicionário de carimbo de tempo de arquivamento não foi emitido”
  • Sintoma. SignatureException com o final no /Type /DocTimeStamp dictionary was emitted into the PDF buffer.
  • Causa provável. O ciclo de arquivamento B-LTA foi executado, mas o dicionário de carimbo de tempo do documento nunca chegou ao buffer. O artefato seria um B-LTA gravado parcialmente, portanto o engine se recusa a retorná-lo.
  • Evidência / diagnóstico. A fábrica SignatureException::documentTimestampNotEmitted() gera esta mensagem. Esta falha de pós-condição é gerada no momento da finalização.
  • Resolução.
    1. Trate a saída como descartada; não distribua o artefato parcial.
    2. Execute o pipeline B-LTA novamente com uma autoridade de carimbo de tempo acessível.
    3. Se a falha se repetir, capture getContext() e a exceção anterior encadeada para um relatório de defeito.
  • Relacionado. Referência de exceções.
  • Essas fábricas definem cert_info como um subject ou thumbprint apenas quando algum deles está disponível; um cert_info vazio é esperado para falhas de recurso e de configuração.
  • Uma solicitação B-LT ou B-LTA sem um cliente Hypertext Transfer Protocol (HTTP) configurado gera SignatureException::httpClientMissing(); a busca de revogação exige um cliente PHP Standards Recommendation (PSR)-18 passado para o orquestrador.
  • Um certificado baseado em um hardware security module (HSM) sem uma implementação de signatário gera SignatureException::hsmSignerMissing(); conecte o signatário ao certificado antes de assinar.

Glossário: nível PAdES · asserção de revogação